@@ -35,19 +35,21 @@ import util from '../util';
3535import OID from '../type/oid' ;
3636import { Curve } from './public_key/elliptic/curves' ;
3737import { UnsupportedError } from '../packet/packet' ;
38+ import ECDHXSymmetricKey from '../type/ecdh_x_symkey' ;
3839
3940/**
4041 * Encrypts data using specified algorithm and public key parameters.
4142 * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
42- * @param {module:enums.publicKey } algo - Public key algorithm
43+ * @param {module:enums.publicKey } keyAlgo - Public key algorithm
44+ * @param {module:enums.symmetric } symmetricAlgo - Cipher algorithm
4345 * @param {Object } publicParams - Algorithm-specific public key parameters
44- * @param {Uint8Array } data - Data to be encrypted
46+ * @param {Uint8Array } data - Session key data to be encrypted
4547 * @param {Uint8Array } fingerprint - Recipient fingerprint
4648 * @returns {Promise<Object> } Encrypted session key parameters.
4749 * @async
4850 */
49- export async function publicKeyEncrypt ( algo , publicParams , data , fingerprint ) {
50- switch ( algo ) {
51+ export async function publicKeyEncrypt ( keyAlgo , symmetricAlgo , publicParams , data , fingerprint ) {
52+ switch ( keyAlgo ) {
5153 case enums . publicKey . rsaEncrypt :
5254 case enums . publicKey . rsaEncryptSign : {
5355 const { n, e } = publicParams ;
@@ -64,6 +66,14 @@ export async function publicKeyEncrypt(algo, publicParams, data, fingerprint) {
6466 oid , kdfParams , data , Q , fingerprint ) ;
6567 return { V, C : new ECDHSymkey ( C ) } ;
6668 }
69+ case enums . publicKey . x25519 : {
70+ const { A } = publicParams ;
71+ const { ephemeralPublicKey, wrappedKey } = await publicKey . elliptic . ecdhX . encrypt (
72+ keyAlgo , data , A ) ;
73+ const C = ECDHXSymmetricKey . fromObject ( { algorithm : symmetricAlgo , wrappedKey } ) ;
74+ return { ephemeralPublicKey, C } ;
75+
76+ }
6777 default :
6878 return [ ] ;
6979 }
@@ -105,6 +115,13 @@ export async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams,
105115 return publicKey . elliptic . ecdh . decrypt (
106116 oid , kdfParams , V , C . data , Q , d , fingerprint ) ;
107117 }
118+ case enums . publicKey . x25519 : {
119+ const { A } = publicKeyParams ;
120+ const { k } = privateKeyParams ;
121+ const { ephemeralPublicKey, C } = sessionKeyParams ;
122+ return publicKey . elliptic . ecdhX . decrypt (
123+ algo , ephemeralPublicKey , C . wrappedKey , A , k ) ;
124+ }
108125 default :
109126 throw new Error ( 'Unknown public key encryption algorithm.' ) ;
110127 }
@@ -160,7 +177,8 @@ export function parsePublicKeyParams(algo, bytes) {
160177 const kdfParams = new KDFParams ( ) ; read += kdfParams . read ( bytes . subarray ( read ) ) ;
161178 return { read : read , publicParams : { oid, Q, kdfParams } } ;
162179 }
163- case enums . publicKey . ed25519 : {
180+ case enums . publicKey . ed25519 :
181+ case enums . publicKey . x25519 : {
164182 const A = bytes . subarray ( read , read + 32 ) ; read += A . length ;
165183 return { read, publicParams : { A } } ;
166184 }
@@ -211,6 +229,10 @@ export function parsePrivateKeyParams(algo, bytes, publicParams) {
211229 const seed = bytes . subarray ( read , read + 32 ) ; read += seed . length ;
212230 return { read, privateParams : { seed } } ;
213231 }
232+ case enums . publicKey . x25519 : {
233+ const k = bytes . subarray ( read , read + 32 ) ; read += k . length ;
234+ return { read, privateParams : { k } } ;
235+ }
214236 default :
215237 throw new UnsupportedError ( 'Unknown public key encryption algorithm.' ) ;
216238 }
@@ -248,6 +270,16 @@ export function parseEncSessionKeyParams(algo, bytes) {
248270 const C = new ECDHSymkey ( ) ; C . read ( bytes . subarray ( read ) ) ;
249271 return { V, C } ;
250272 }
273+ // Algorithm-Specific Fields for X25519 encrypted session keys:
274+ // - 32 octets representing an ephemeral X25519 public key.
275+ // - A one-octet size of the following fields.
276+ // - The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
277+ // - The encrypted session key.
278+ case enums . publicKey . x25519 : {
279+ const ephemeralPublicKey = bytes . subarray ( read , read + 32 ) ; read += ephemeralPublicKey . length ;
280+ const C = new ECDHXSymmetricKey ( ) ; C . read ( bytes . subarray ( read ) ) ;
281+ return { ephemeralPublicKey, C } ;
282+ }
251283 default :
252284 throw new UnsupportedError ( 'Unknown public key encryption algorithm.' ) ;
253285 }
@@ -261,7 +293,7 @@ export function parseEncSessionKeyParams(algo, bytes) {
261293 */
262294export function serializeParams ( algo , params ) {
263295 // Some algorithms do not rely on MPIs to store the binary params
264- const algosWithNativeRepresentation = new Set ( [ enums . publicKey . ed25519 ] ) ;
296+ const algosWithNativeRepresentation = new Set ( [ enums . publicKey . ed25519 , enums . publicKey . x25519 ] ) ;
265297 const orderedParams = Object . keys ( params ) . map ( name => {
266298 const param = params [ name ] ;
267299 if ( ! util . isUint8Array ( param ) ) return param . write ( ) ;
@@ -313,6 +345,11 @@ export function generateParams(algo, bits, oid) {
313345 privateParams : { seed } ,
314346 publicParams : { A }
315347 } ) ) ;
348+ case enums . publicKey . x25519 :
349+ return publicKey . elliptic . ecdhX . generate ( algo ) . then ( ( { A, k } ) => ( {
350+ privateParams : { k } ,
351+ publicParams : { A }
352+ } ) ) ;
316353 case enums . publicKey . dsa :
317354 case enums . publicKey . elgamal :
318355 throw new Error ( 'Unsupported algorithm for key generation.' ) ;
@@ -369,6 +406,11 @@ export async function validateParams(algo, publicParams, privateParams) {
369406 const { seed } = privateParams ;
370407 return publicKey . elliptic . eddsa . validateParams ( algo , A , seed ) ;
371408 }
409+ case enums . publicKey . x25519 : {
410+ const { A } = publicParams ;
411+ const { k } = privateParams ;
412+ return publicKey . elliptic . ecdhX . validateParams ( algo , A , k ) ;
413+ }
372414 default :
373415 throw new Error ( 'Unknown public key algorithm.' ) ;
374416 }
0 commit comments