diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/crypto/00_crypto.js | 68 | ||||
-rw-r--r-- | ext/crypto/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/crypto/lib.rs | 75 |
3 files changed, 141 insertions, 3 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index fdd0f612d..f0ba0b4bf 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -1278,6 +1278,28 @@ // 3. return data.buffer; } + case "spki": { + // 1. + if (key[_type] !== "public") { + throw new DOMException( + "Key is not a public key", + "InvalidAccessError", + ); + } + + // 2. + const data = await core.opAsync( + "op_crypto_export_key", + { + key: innerKey, + format: "spki", + algorithm: "RSASSA-PKCS1-v1_5", + }, + ); + + // 3. + return data.buffer; + } default: throw new DOMException("Not implemented", "NotSupportedError"); } @@ -1307,6 +1329,29 @@ // 3. return data.buffer; } + case "spki": { + // 1. + if (key[_type] !== "public") { + throw new DOMException( + "Key is not a public key", + "InvalidAccessError", + ); + } + + // 2. + const data = await core.opAsync( + "op_crypto_export_key", + { + key: innerKey, + format: "spki", + algorithm: "RSA-PSS", + hash: key[_algorithm].hash.name, + }, + ); + + // 3. + return data.buffer; + } default: throw new DOMException("Not implemented", "NotSupportedError"); } @@ -1336,6 +1381,29 @@ // 3. return data.buffer; } + case "spki": { + // 1. + if (key[_type] !== "public") { + throw new DOMException( + "Key is not a public key", + "InvalidAccessError", + ); + } + + // 2. + const data = await core.opAsync( + "op_crypto_export_key", + { + key: innerKey, + format: "spki", + algorithm: "RSA-OAEP", + hash: key[_algorithm].hash.name, + }, + ); + + // 3. + return data.buffer; + } default: throw new DOMException("Not implemented", "NotSupportedError"); } diff --git a/ext/crypto/Cargo.toml b/ext/crypto/Cargo.toml index 2aa55599e..d04f8dc33 100644 --- a/ext/crypto/Cargo.toml +++ b/ext/crypto/Cargo.toml @@ -24,5 +24,6 @@ rsa = { version = "0.5.0", default-features = false, features = ["std"] } serde = { version = "1.0.129", features = ["derive"] } sha-1 = "0.9.7" sha2 = "0.9.5" +spki = "0.4.1" tokio = { version = "1.10.1", features = ["full"] } uuid = { version = "0.8.2", features = ["v4"] } diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs index a562eaf01..2db629c94 100644 --- a/ext/crypto/lib.rs +++ b/ext/crypto/lib.rs @@ -271,6 +271,7 @@ pub async fn op_crypto_generate_key( pub enum KeyFormat { Raw, Pkcs8, + Spki, } #[derive(Deserialize)] @@ -631,7 +632,27 @@ pub async fn op_crypto_export_key( Ok(pk_info.to_der().as_ref().to_vec().into()) } - // TODO(@littledivy): spki + KeyFormat::Spki => { + // public_key is a PKCS#1 DER-encoded public key + + let subject_public_key = &args.key.data; + + // the SPKI structure + let key_info = spki::SubjectPublicKeyInfo { + algorithm: spki::AlgorithmIdentifier { + // rsaEncryption(1) + oid: spki::ObjectIdentifier::new("1.2.840.113549.1.1.1"), + // parameters field should not be ommited (None). + // It MUST have ASN.1 type NULL. + parameters: Some(asn1::Any::from(asn1::Null)), + }, + subject_public_key, + }; + + // Infallible based on spec because of the way we import and generate keys. + let spki_der = key_info.to_vec().unwrap(); + Ok(spki_der.into()) + } // TODO(@littledivy): jwk _ => unreachable!(), } @@ -668,7 +689,31 @@ pub async fn op_crypto_export_key( Ok(pk_info.to_der().as_ref().to_vec().into()) } - // TODO(@littledivy): spki + KeyFormat::Spki => { + // Intentionally unused but required. Not encoded into SPKI (see below). + let _hash = args + .hash + .ok_or_else(|| type_error("Missing argument hash".to_string()))?; + + // public_key is a PKCS#1 DER-encoded public key + let subject_public_key = &args.key.data; + + // the SPKI structure + let key_info = spki::SubjectPublicKeyInfo { + algorithm: spki::AlgorithmIdentifier { + // rsaEncryption(1) + oid: spki::ObjectIdentifier::new("1.2.840.113549.1.1.1"), + // parameters field should not be ommited (None). + // It MUST have ASN.1 type NULL. + parameters: Some(asn1::Any::from(asn1::Null)), + }, + subject_public_key, + }; + + // Infallible based on spec because of the way we import and generate keys. + let spki_der = key_info.to_vec().unwrap(); + Ok(spki_der.into()) + } // TODO(@littledivy): jwk _ => unreachable!(), } @@ -705,7 +750,31 @@ pub async fn op_crypto_export_key( Ok(pk_info.to_der().as_ref().to_vec().into()) } - // TODO(@littledivy): spki + KeyFormat::Spki => { + // Intentionally unused but required. Not encoded into SPKI (see below). + let _hash = args + .hash + .ok_or_else(|| type_error("Missing argument hash".to_string()))?; + + // public_key is a PKCS#1 DER-encoded public key + let subject_public_key = &args.key.data; + + // the SPKI structure + let key_info = spki::SubjectPublicKeyInfo { + algorithm: spki::AlgorithmIdentifier { + // rsaEncryption(1) + oid: spki::ObjectIdentifier::new("1.2.840.113549.1.1.1"), + // parameters field should not be ommited (None). + // It MUST have ASN.1 type NULL. + parameters: Some(asn1::Any::from(asn1::Null)), + }, + subject_public_key, + }; + + // Infallible based on spec because of the way we import and generate keys. + let spki_der = key_info.to_vec().unwrap(); + Ok(spki_der.into()) + } // TODO(@littledivy): jwk _ => unreachable!(), } |