Skip to content

About the encryption and the decryption of the socekt communication between the browser client and the node server #2618

Closed

Description

@OFEII

Q: About the encryption and the decryption of the socekt communication between the browser client and the node server

For the privacy of users, it is now necessary to encrypt and decrypt the data between the browser client and the node server socekt communication.

By studying the source code of vscode, I found some code fragments related to data about the socekt communication, likebrowser/browserSocketFactory.tsandnode/ipc.net.ts.

I tried countless times, but all failed. I think the key of this question lies in the conversion of data types(like uint8Array, VSbuffer...)

What puzzles me is that when I convert the received buffer from the browser client (VsBuffer => string => VsBuffer) in the node/ipc.net.ts. The result of the buffer before and after the conversion is unexpected, the length of the VsBuffer is the same, but a small part of the converted Vsbuffer has changed. I guess it may be caused by garbled characters after being converted to string, so what is the coding scheme of the garbled characters, unlike ASCII, UTF-8, Unicode..., as shown below:

diff of conversion

// some function about conversion 
// Vsbuffer => string
VsBuffer.toString()

// string => Vsbuffer(built-in-method) 
VsBuffer.fromString(str: string)

// string => Vsbuffer(use)
function str2buff(str: string): VSBuffer  {
	let arr = []
	for (let i = 0, j = str.length; i < j; ++i) {
		arr.push(str.charCodeAt(i))
	}
	return VSBuffer.wrap(new Uint8Array(arr))
}

But if I use the built-in-method of the Vsbuffer to convert (VsBuffer => string => VsBuffer), the length and buffer content of the buffer before and after is inconsistent.

Now my thoughts are blocked, maybe. How can I complete this function by modifying the source code of vscode?img

Activity

  1. oxy commented on Jan 22, 2021

    @oxy

    I'm fairly new to the VSCode internals - but if it works how I think it does, shouldn't we have transport-layer encryption provided by the websocket if we have a cert provided?

  2. OFEII commented on Jan 25, 2021

    @OFEII
    Author

    I'm fairly new to the VSCode internals - but if it works how I think it does, shouldn't we have transport-layer encryption provided by the websocket if we have a cert provided?

    You mean the transport layer encryption at the webSocket, I know, but I want to encrypt data on the application layer😅

  3. code-asher commented on Jan 25, 2021

    @code-asher
    Member

    There is an abstraction on top of the messages sent across the socket. There is a header with some information then a body after that (you can see the documentation for this in ipc.net.ts). Probably trying to convert the header portion to a string is causing the issue.

    There are further abstractions on top of that in some cases, like with channels which add their own header and body as well. There may be others but those are all the ones I know of.

  4. code-asher commented on Jan 25, 2021

    @code-asher
    Member

    In fact I don't think there's any guarantee the body is a string so any kind of general conversion is probably going to have issues.

  5. OFEII commented on Feb 18, 2021

    @OFEII
    Author

    In fact I don't think there's any guarantee the body is a string so any kind of general conversion is probably going to have issues.

    Now I have completed the first simply encryption, split the client data into header, body, footer, then encrypt the body data(code fragment), and then divide the body into header, body, and footer when the server receives it in the _acceptChunk function, and then fire the body(this.onData.fire(body)) After decrypt the body data and splice it back.

    However, this kind of websocket encryption is successful under a certain amount of code (about 1200 lines of code), but too much code will trigger the reconnection mechanism due to acceptChunck's block transmission.

    Is there any way to solve this problem or other ideas of encryption? Help😅
    image

  6. code-asher commented on Feb 18, 2021

    @code-asher
    Member
  7. OFEII commented on Feb 19, 2021

    @OFEII
    Author

    Couldn't you encrypt and decrypt the entire message without having to do any splitting?

    If you do not split, because of some special identifiers of header and footer, the encrypted data will not be successfully decrypted on the server. Now I am using CryptoJS AES encryption and decryption. Since the string can be encrypted and decrypted directly after splitting, there is no need to consider converting to base64.

    The problem now lies in the acceptChunck's block transmission when the amount of code is large(about 1200+ lines of code). I think this splitting may have limitations.

    Are there any other good encryption methods to fix?🥺

    // encrypt and decrypt after splitting
    
    import * as CryptoJS from 'crypto-js'
    // 1. the encrypt func in the client
    function encrypt(word: string): string {
      let encJson = CryptoJS.AES.encrypt(JSON.stringify(word), key).toString()
      let encData = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(encJson))
      return encData
    }
    
    //2. the decrypt func in the node server
    function decrypt(word: string): string {
      let decData = CryptoJS.enc.Base64.parse(word).toString(CryptoJS.enc.Utf8)
      let bytes = CryptoJS.AES.decrypt(decData, key).toString(CryptoJS.enc.Utf8)
      return JSON.parse(bytes)
    }
  8. code-asher commented on Feb 22, 2021

    @code-asher
    Member

    I think splitting will be dangerous because there's no guarantee a chunk has a header or a body. It could be half a header or have multiple headers and bodies or not have any headers and bodies at all or have a body that itself also has a header and a body, etc.

    You might have success if you encrypt and decrypt at the points where the socket sends and receives messages.

    Maybe here:

    https://github.com/cdr/code-server/blob/fc6d123da59a4e5a675ac8e080f66e032ba01a1b/lib/vscode/src/vs/base/parts/ipc/node/ipc.net.ts#L31

     const listener = (buff: Buffer) => _listener(VSBuffer.wrap(decrypt(buff))); 

    And here:

    https://github.com/cdr/code-server/blob/fc6d123da59a4e5a675ac8e080f66e032ba01a1b/lib/vscode/src/vs/base/parts/ipc/node/ipc.net.ts#L64

     this.socket.write(encrypt(<Buffer>buffer.buffer));

    Where encrypt and decrypt are capable of encrypting and decrypting an arbitrary Buffer.

  9. code-asher commented on Feb 22, 2021

    @code-asher
    Member

    I'm going to move this to a discussion, please feel free to continue commenting there!

  10. locked and limited conversation to collaborators on Feb 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew user visible feature

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions