- {`contentKey = randomBytes(32) # 256 bits
-nonce = randomBytes(24) # 192 bits
-ciphertext = XChaCha20-Poly1305(
- key = contentKey,
- nonce = nonce,
- plaintext = UTF8(message)
-)`}
-
- -
-
- {`messageSecret = contentKey || nonce
+
+ Recipient key envelope
+
+
+
+ The client creates an ephemeral secp256k1 key pair for the message.
+
+
+ ECDH combines the ephemeral private key with the recipient's
+ long-term public key.
+
+
+ The x-coordinate of the shared point is used as a 32-byte AES wrapping
+ key.
+
+
+ The 56-byte message secret — content key followed by nonce — is wrapped
+ with AES-CBC and PKCS#7 padding using a random 16-byte IV.
+
+
+ The envelope contains the IV, encrypted message secret, and ephemeral
+ public key. The content key is never sent in plaintext.
+
+
+ {`messageSecret = contentKey || nonce
ephemeral = secp256k1.randomKeyPair()
sharedPoint = ECDH(ephemeral.private, recipient.public)
wrappingKey = sharedPoint.x[0..31]
-keyEnvelope = Base64(iv || AES-CBC(wrappingKey, messageSecret) || ephemeral.public)`}
-
+keyEnvelope = Base64(iv || AES-CBC(wrappingKey, messageSecret) || ephemeral.public)`}
-
- RAC2 || salt[16] || iv[12] || AES-256-GCM-ciphertext-and-tag
-
-
- {`input
- → DEFLATE compression
- → PBKDF2(password, "rosetta", 1,000 iterations)
- → AES-CBC with random 16-byte IV
- → Base64(iv) : Base64(ciphertext)`}
-
- -
-
-
-