@@ -26,6 +26,7 @@ use rsa::pkcs1::DecodeRsaPrivateKey as _;
26
26
use rsa:: pkcs1:: DecodeRsaPublicKey ;
27
27
use rsa:: pkcs1:: EncodeRsaPrivateKey as _;
28
28
use rsa:: pkcs1:: EncodeRsaPublicKey ;
29
+ use rsa:: traits:: PrivateKeyParts ;
29
30
use rsa:: traits:: PublicKeyParts ;
30
31
use rsa:: RsaPrivateKey ;
31
32
use rsa:: RsaPublicKey ;
@@ -255,6 +256,16 @@ impl EcPrivateKey {
255
256
EcPrivateKey :: P384 ( key) => EcPublicKey :: P384 ( key. public_key ( ) ) ,
256
257
}
257
258
}
259
+
260
+ pub fn to_jwk ( & self ) -> Result < JwkEcKey , AsymmetricPrivateKeyJwkError > {
261
+ match self {
262
+ EcPrivateKey :: P224 ( _) => {
263
+ Err ( AsymmetricPrivateKeyJwkError :: UnsupportedJwkEcCurveP224 )
264
+ }
265
+ EcPrivateKey :: P256 ( key) => Ok ( key. to_jwk ( ) ) ,
266
+ EcPrivateKey :: P384 ( key) => Ok ( key. to_jwk ( ) ) ,
267
+ }
268
+ }
258
269
}
259
270
260
271
// https://oidref.com/
@@ -1107,6 +1118,16 @@ fn bytes_to_b64(bytes: &[u8]) -> String {
1107
1118
BASE64_URL_SAFE_NO_PAD . encode ( bytes)
1108
1119
}
1109
1120
1121
+ #[ derive( Debug , thiserror:: Error ) ]
1122
+ pub enum AsymmetricPrivateKeyJwkError {
1123
+ #[ error( "key is not an asymmetric private key" ) ]
1124
+ KeyIsNotAsymmetricPrivateKey ,
1125
+ #[ error( "Unsupported JWK EC curve: P224" ) ]
1126
+ UnsupportedJwkEcCurveP224 ,
1127
+ #[ error( "jwk export not implemented for this key type" ) ]
1128
+ JwkExportNotImplementedForKeyType ,
1129
+ }
1130
+
1110
1131
#[ derive( Debug , thiserror:: Error ) ]
1111
1132
pub enum AsymmetricPublicKeyJwkError {
1112
1133
#[ error( "key is not an asymmetric public key" ) ]
@@ -1328,7 +1349,73 @@ pub enum AsymmetricPrivateKeyDerError {
1328
1349
UnsupportedKeyType ( String ) ,
1329
1350
}
1330
1351
1352
+ // https://datatracker.ietf.org/doc/html/rfc7518#section-6.3.2
1353
+ fn rsa_private_to_jwk ( key : & RsaPrivateKey ) -> deno_core:: serde_json:: Value {
1354
+ let n = key. n ( ) ;
1355
+ let e = key. e ( ) ;
1356
+ let d = key. d ( ) ;
1357
+ let p = & key. primes ( ) [ 0 ] ;
1358
+ let q = & key. primes ( ) [ 1 ] ;
1359
+ let dp = key. dp ( ) ;
1360
+ let dq = key. dq ( ) ;
1361
+ let qi = key. crt_coefficient ( ) ;
1362
+ let oth = & key. primes ( ) [ 2 ..] ;
1363
+
1364
+ let mut obj = deno_core:: serde_json:: json!( {
1365
+ "kty" : "RSA" ,
1366
+ "n" : bytes_to_b64( & n. to_bytes_be( ) ) ,
1367
+ "e" : bytes_to_b64( & e. to_bytes_be( ) ) ,
1368
+ "d" : bytes_to_b64( & d. to_bytes_be( ) ) ,
1369
+ "p" : bytes_to_b64( & p. to_bytes_be( ) ) ,
1370
+ "q" : bytes_to_b64( & q. to_bytes_be( ) ) ,
1371
+ "dp" : dp. map( |dp| bytes_to_b64( & dp. to_bytes_be( ) ) ) ,
1372
+ "dq" : dq. map( |dq| bytes_to_b64( & dq. to_bytes_be( ) ) ) ,
1373
+ "qi" : qi. map( |qi| bytes_to_b64( & qi. to_bytes_be( ) ) ) ,
1374
+ } ) ;
1375
+
1376
+ if !oth. is_empty ( ) {
1377
+ obj[ "oth" ] = deno_core:: serde_json:: json!( oth
1378
+ . iter( )
1379
+ . map( |o| o. to_bytes_be( ) )
1380
+ . collect:: <Vec <_>>( ) ) ;
1381
+ }
1382
+
1383
+ obj
1384
+ }
1385
+
1331
1386
impl AsymmetricPrivateKey {
1387
+ fn export_jwk (
1388
+ & self ,
1389
+ ) -> Result < deno_core:: serde_json:: Value , AsymmetricPrivateKeyJwkError > {
1390
+ match self {
1391
+ AsymmetricPrivateKey :: Rsa ( key) => Ok ( rsa_private_to_jwk ( key) ) ,
1392
+ AsymmetricPrivateKey :: RsaPss ( key) => Ok ( rsa_private_to_jwk ( & key. key ) ) ,
1393
+ AsymmetricPrivateKey :: Ec ( key) => {
1394
+ let jwk = key. to_jwk ( ) ?;
1395
+ Ok ( deno_core:: serde_json:: json!( jwk) )
1396
+ }
1397
+ AsymmetricPrivateKey :: X25519 ( static_secret) => {
1398
+ let bytes = static_secret. to_bytes ( ) ;
1399
+
1400
+ Ok ( deno_core:: serde_json:: json!( {
1401
+ "kty" : "OKP" ,
1402
+ "crv" : "X25519" ,
1403
+ "d" : bytes_to_b64( & bytes) ,
1404
+ } ) )
1405
+ }
1406
+ AsymmetricPrivateKey :: Ed25519 ( key) => {
1407
+ let bytes = key. to_bytes ( ) ;
1408
+
1409
+ Ok ( deno_core:: serde_json:: json!( {
1410
+ "kty" : "OKP" ,
1411
+ "crv" : "Ed25519" ,
1412
+ "d" : bytes_to_b64( & bytes) ,
1413
+ } ) )
1414
+ }
1415
+ _ => Err ( AsymmetricPrivateKeyJwkError :: JwkExportNotImplementedForKeyType ) ,
1416
+ }
1417
+ }
1418
+
1332
1419
fn export_der (
1333
1420
& self ,
1334
1421
typ : & str ,
@@ -2329,6 +2416,28 @@ pub fn op_node_export_private_key_pem(
2329
2416
Ok ( String :: from_utf8 ( out) . expect ( "invalid pem is not possible" ) )
2330
2417
}
2331
2418
2419
+ #[ derive( Debug , thiserror:: Error ) ]
2420
+ pub enum ExportPrivateKeyJwkError {
2421
+ #[ error( transparent) ]
2422
+ AsymmetricPublicKeyJwk ( #[ from] AsymmetricPrivateKeyJwkError ) ,
2423
+ #[ error( "very large data" ) ]
2424
+ VeryLargeData ,
2425
+ #[ error( transparent) ]
2426
+ Der ( #[ from] der:: Error ) ,
2427
+ }
2428
+
2429
+ #[ op2]
2430
+ #[ serde]
2431
+ pub fn op_node_export_private_key_jwk (
2432
+ #[ cppgc] handle : & KeyObjectHandle ,
2433
+ ) -> Result < deno_core:: serde_json:: Value , ExportPrivateKeyJwkError > {
2434
+ let private_key = handle
2435
+ . as_private_key ( )
2436
+ . ok_or ( AsymmetricPrivateKeyJwkError :: KeyIsNotAsymmetricPrivateKey ) ?;
2437
+
2438
+ Ok ( private_key. export_jwk ( ) ?)
2439
+ }
2440
+
2332
2441
#[ op2]
2333
2442
#[ buffer]
2334
2443
pub fn op_node_export_private_key_der (
0 commit comments