Skip to content

Commit 319c9e2

Browse files
ldanilekConvex, Inc.
authored and
Convex, Inc.
committed
[CX-6055] [crypto] implement exportKey (#23813)
copy from deno (with license). the only code change is i removed `SafeArrayIterator` (a deno primordial). enable round trip tests. GitOrigin-RevId: 70162f6c15f6c6b918bb03ed004d41fe186246ad
1 parent 083f73b commit 319c9e2

File tree

11 files changed

+1294
-43
lines changed

11 files changed

+1294
-43
lines changed

crates/isolate/src/execution_scope.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,14 @@ impl<'a, 'b: 'a, RT: Runtime, E: IsolateEnvironment<RT>> ExecutionScope<'a, 'b,
585585
"crypto/importPkcs8Ed25519" => self.op_crypto_import_pkcs8_ed25519(args, rv)?,
586586
"crypto/importSpkiX25519" => self.op_crypto_import_spki_x25519(args, rv)?,
587587
"crypto/importPkcs8X25519" => self.op_crypto_import_pkcs8_x25519(args, rv)?,
588+
"crypto/base64UrlEncode" => self.op_crypto_base64_url_encode(args, rv)?,
588589
"crypto/base64UrlDecode" => self.op_crypto_base64_url_decode(args, rv)?,
590+
"crypto/exportKey" => self.op_crypto_export_key(args, rv)?,
591+
"crypto/exportSpkiEd25519" => self.op_crypto_export_spki_ed25519(args, rv)?,
592+
"crypto/exportPkcs8Ed25519" => self.op_crypto_export_pkcs8_ed25519(args, rv)?,
593+
"crypto/JwkXEd25519" => self.op_crypto_jwk_x_ed25519(args, rv)?,
594+
"crypto/exportSpkiX25519" => self.op_crypto_export_spki_x25519(args, rv)?,
595+
"crypto/exportPkcs8X25519" => self.op_crypto_export_pkcs8_x25519(args, rv)?,
589596
_ => {
590597
anyhow::bail!(ErrorMetadata::bad_request(
591598
"UnknownOperation",

crates/isolate/src/ops/crypto/ed25519.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,27 @@ use deno_core::{
77
};
88
use elliptic_curve::pkcs8::PrivateKeyInfo;
99
use p256::pkcs8::der::Decode as _;
10-
use ring::signature::Ed25519KeyPair;
10+
use ring::signature::{
11+
Ed25519KeyPair,
12+
KeyPair,
13+
};
1114
use spki::{
1215
der::{
16+
asn1::BitString,
1317
AnyRef,
1418
Decode,
19+
Encode,
1520
},
1621
SubjectPublicKeyInfo,
1722
};
1823

19-
use super::CryptoOps;
24+
use super::{
25+
shared::{
26+
custom_error,
27+
AnyError,
28+
},
29+
CryptoOps,
30+
};
2031

2132
// id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
2233
pub const ED25519_OID: const_oid::ObjectIdentifier =
@@ -79,4 +90,46 @@ impl CryptoOps {
7990
}
8091
Some(pk_info.private_key[2..].to_vec().into())
8192
}
93+
94+
pub fn export_spki_ed25519(pubkey: &[u8]) -> Result<ToJsBuffer, AnyError> {
95+
let key_info = spki::SubjectPublicKeyInfo {
96+
algorithm: spki::AlgorithmIdentifierOwned {
97+
// id-Ed25519
98+
oid: ED25519_OID,
99+
parameters: None,
100+
},
101+
subject_public_key: BitString::from_bytes(pubkey)?,
102+
};
103+
Ok(key_info
104+
.to_der()
105+
.map_err(|_| custom_error("DOMExceptionOperationError", "Failed to export key"))?
106+
.into())
107+
}
108+
109+
pub fn export_pkcs8_ed25519(pkey: &[u8]) -> Result<ToJsBuffer, AnyError> {
110+
// This should probably use OneAsymmetricKey instead
111+
let pk_info = rsa::pkcs8::PrivateKeyInfo {
112+
public_key: None,
113+
algorithm: rsa::pkcs8::AlgorithmIdentifierRef {
114+
// id-Ed25519
115+
oid: ED25519_OID,
116+
parameters: None,
117+
},
118+
private_key: pkey, // OCTET STRING
119+
};
120+
121+
let mut buf = Vec::new();
122+
pk_info.encode_to_vec(&mut buf)?;
123+
Ok(buf.into())
124+
}
125+
126+
// 'x' from Section 2 of RFC 8037
127+
// https://www.rfc-editor.org/rfc/rfc8037#section-2
128+
pub fn jwk_x_ed25519(pkey: &[u8]) -> Result<String, AnyError> {
129+
let pair = Ed25519KeyPair::from_seed_unchecked(pkey).map_err(|e| anyhow::anyhow!(e))?;
130+
Ok(base64::encode_config(
131+
pair.public_key().as_ref(),
132+
base64::URL_SAFE_NO_PAD,
133+
))
134+
}
82135
}

0 commit comments

Comments
 (0)