mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
fix(ext/crypto): interoperable import/export (#16153)
This PR updates RSA key import/export to a state which is interoperable with other implementations. For RSA the only OID in and out is `rsaEncryption`. For EC the only OID in and out is `id-ecpublickey` (fixed in #16152). see https://github.com/w3c/webcrypto/issues/307#issuecomment-995813032 see https://github.com/w3c/webcrypto/issues/307 see https://github.com/w3c/webcrypto/pull/305 see https://github.com/nodejs/node/pull/42816
This commit is contained in:
parent
aa710aac98
commit
0d042d8e54
4 changed files with 75 additions and 446 deletions
|
@ -383,21 +383,6 @@ Deno.test(async function generateImportHmacJwk() {
|
||||||
const pkcs8TestVectors = [
|
const pkcs8TestVectors = [
|
||||||
// rsaEncryption
|
// rsaEncryption
|
||||||
{ pem: "cli/tests/testdata/webcrypto/id_rsaEncryption.pem", hash: "SHA-256" },
|
{ pem: "cli/tests/testdata/webcrypto/id_rsaEncryption.pem", hash: "SHA-256" },
|
||||||
// id-RSASSA-PSS (sha256)
|
|
||||||
// `openssl genpkey -algorithm rsa-pss -pkeyopt rsa_pss_keygen_md:sha256 -out id_rsassaPss.pem`
|
|
||||||
{ pem: "cli/tests/testdata/webcrypto/id_rsassaPss.pem", hash: "SHA-256" },
|
|
||||||
// id-RSASSA-PSS (default parameters)
|
|
||||||
// `openssl genpkey -algorithm rsa-pss -out id_rsassaPss.pem`
|
|
||||||
{
|
|
||||||
pem: "cli/tests/testdata/webcrypto/id_rsassaPss_default.pem",
|
|
||||||
hash: "SHA-1",
|
|
||||||
},
|
|
||||||
// id-RSASSA-PSS (default hash)
|
|
||||||
// `openssl genpkey -algorithm rsa-pss -pkeyopt rsa_pss_keygen_saltlen:30 -out rsaPss_saltLen_30.pem`
|
|
||||||
{
|
|
||||||
pem: "cli/tests/testdata/webcrypto/id_rsassaPss_saltLen_30.pem",
|
|
||||||
hash: "SHA-1",
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
Deno.test({ permissions: { read: true } }, async function importRsaPkcs8() {
|
Deno.test({ permissions: { read: true } }, async function importRsaPkcs8() {
|
||||||
|
@ -435,6 +420,57 @@ Deno.test({ permissions: { read: true } }, async function importRsaPkcs8() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const nonInteroperableVectors = [
|
||||||
|
// id-RSASSA-PSS (sha256)
|
||||||
|
// `openssl genpkey -algorithm rsa-pss -pkeyopt rsa_pss_keygen_md:sha256 -out id_rsassaPss.pem`
|
||||||
|
{ pem: "cli/tests/testdata/webcrypto/id_rsassaPss.pem", hash: "SHA-256" },
|
||||||
|
// id-RSASSA-PSS (default parameters)
|
||||||
|
// `openssl genpkey -algorithm rsa-pss -out id_rsassaPss.pem`
|
||||||
|
{
|
||||||
|
pem: "cli/tests/testdata/webcrypto/id_rsassaPss_default.pem",
|
||||||
|
hash: "SHA-1",
|
||||||
|
},
|
||||||
|
// id-RSASSA-PSS (default hash)
|
||||||
|
// `openssl genpkey -algorithm rsa-pss -pkeyopt rsa_pss_keygen_saltlen:30 -out rsaPss_saltLen_30.pem`
|
||||||
|
{
|
||||||
|
pem: "cli/tests/testdata/webcrypto/id_rsassaPss_saltLen_30.pem",
|
||||||
|
hash: "SHA-1",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { read: true } },
|
||||||
|
async function importNonInteroperableRsaPkcs8() {
|
||||||
|
const pemHeader = "-----BEGIN PRIVATE KEY-----";
|
||||||
|
const pemFooter = "-----END PRIVATE KEY-----";
|
||||||
|
for (const { pem, hash } of nonInteroperableVectors) {
|
||||||
|
const keyFile = await Deno.readTextFile(pem);
|
||||||
|
const pemContents = keyFile.substring(
|
||||||
|
pemHeader.length,
|
||||||
|
keyFile.length - pemFooter.length,
|
||||||
|
);
|
||||||
|
const binaryDerString = atob(pemContents);
|
||||||
|
const binaryDer = new Uint8Array(binaryDerString.length);
|
||||||
|
for (let i = 0; i < binaryDerString.length; i++) {
|
||||||
|
binaryDer[i] = binaryDerString.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
await assertRejects(
|
||||||
|
() =>
|
||||||
|
crypto.subtle.importKey(
|
||||||
|
"pkcs8",
|
||||||
|
binaryDer,
|
||||||
|
{ name: "RSA-PSS", hash },
|
||||||
|
true,
|
||||||
|
["sign"],
|
||||||
|
),
|
||||||
|
DOMException,
|
||||||
|
"unsupported algorithm",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// deno-fmt-ignore
|
// deno-fmt-ignore
|
||||||
const asn1AlgorithmIdentifier = new Uint8Array([
|
const asn1AlgorithmIdentifier = new Uint8Array([
|
||||||
0x02, 0x01, 0x00, // INTEGER
|
0x02, 0x01, 0x00, // INTEGER
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::key::CryptoNamedCurve;
|
use crate::key::CryptoNamedCurve;
|
||||||
use crate::shared::*;
|
use crate::shared::*;
|
||||||
use crate::OaepPrivateKeyParameters;
|
|
||||||
use crate::PssPrivateKeyParameters;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op;
|
use deno_core::op;
|
||||||
use deno_core::ZeroCopyBuf;
|
use deno_core::ZeroCopyBuf;
|
||||||
|
@ -52,11 +50,11 @@ pub enum KeyData {
|
||||||
#[serde(rename_all = "camelCase", tag = "algorithm")]
|
#[serde(rename_all = "camelCase", tag = "algorithm")]
|
||||||
pub enum ImportKeyOptions {
|
pub enum ImportKeyOptions {
|
||||||
#[serde(rename = "RSASSA-PKCS1-v1_5")]
|
#[serde(rename = "RSASSA-PKCS1-v1_5")]
|
||||||
RsassaPkcs1v15 { hash: ShaHash },
|
RsassaPkcs1v15 {},
|
||||||
#[serde(rename = "RSA-PSS")]
|
#[serde(rename = "RSA-PSS")]
|
||||||
RsaPss { hash: ShaHash },
|
RsaPss {},
|
||||||
#[serde(rename = "RSA-OAEP")]
|
#[serde(rename = "RSA-OAEP")]
|
||||||
RsaOaep { hash: ShaHash },
|
RsaOaep {},
|
||||||
#[serde(rename = "ECDSA", rename_all = "camelCase")]
|
#[serde(rename = "ECDSA", rename_all = "camelCase")]
|
||||||
Ecdsa { named_curve: EcNamedCurve },
|
Ecdsa { named_curve: EcNamedCurve },
|
||||||
#[serde(rename = "ECDH", rename_all = "camelCase")]
|
#[serde(rename = "ECDH", rename_all = "camelCase")]
|
||||||
|
@ -91,11 +89,9 @@ pub fn op_crypto_import_key(
|
||||||
key_data: KeyData,
|
key_data: KeyData,
|
||||||
) -> Result<ImportKeyResult, AnyError> {
|
) -> Result<ImportKeyResult, AnyError> {
|
||||||
match opts {
|
match opts {
|
||||||
ImportKeyOptions::RsassaPkcs1v15 { hash } => {
|
ImportKeyOptions::RsassaPkcs1v15 {} => import_key_rsassa(key_data),
|
||||||
import_key_rsassa(key_data, hash)
|
ImportKeyOptions::RsaPss {} => import_key_rsapss(key_data),
|
||||||
}
|
ImportKeyOptions::RsaOaep {} => import_key_rsaoaep(key_data),
|
||||||
ImportKeyOptions::RsaPss { hash } => import_key_rsapss(key_data, hash),
|
|
||||||
ImportKeyOptions::RsaOaep { hash } => import_key_rsaoaep(key_data, hash),
|
|
||||||
ImportKeyOptions::Ecdsa { named_curve }
|
ImportKeyOptions::Ecdsa { named_curve }
|
||||||
| ImportKeyOptions::Ecdh { named_curve } => {
|
| ImportKeyOptions::Ecdh { named_curve } => {
|
||||||
import_key_ec(key_data, named_curve)
|
import_key_ec(key_data, named_curve)
|
||||||
|
@ -193,7 +189,6 @@ fn import_key_rsa_jwk(
|
||||||
|
|
||||||
fn import_key_rsassa(
|
fn import_key_rsassa(
|
||||||
key_data: KeyData,
|
key_data: KeyData,
|
||||||
hash: ShaHash,
|
|
||||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||||
match key_data {
|
match key_data {
|
||||||
KeyData::Spki(data) => {
|
KeyData::Spki(data) => {
|
||||||
|
@ -204,26 +199,9 @@ fn import_key_rsassa(
|
||||||
// 4-5.
|
// 4-5.
|
||||||
let alg = pk_info.algorithm.oid;
|
let alg = pk_info.algorithm.oid;
|
||||||
|
|
||||||
// 6.
|
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||||
let pk_hash = match alg {
|
if alg != RSA_ENCRYPTION_OID {
|
||||||
// rsaEncryption
|
return Err(data_error("unsupported algorithm"));
|
||||||
RSA_ENCRYPTION_OID => None,
|
|
||||||
// sha1WithRSAEncryption
|
|
||||||
SHA1_RSA_ENCRYPTION_OID => Some(ShaHash::Sha1),
|
|
||||||
// sha256WithRSAEncryption
|
|
||||||
SHA256_RSA_ENCRYPTION_OID => Some(ShaHash::Sha256),
|
|
||||||
// sha384WithRSAEncryption
|
|
||||||
SHA384_RSA_ENCRYPTION_OID => Some(ShaHash::Sha384),
|
|
||||||
// sha512WithRSAEncryption
|
|
||||||
SHA512_RSA_ENCRYPTION_OID => Some(ShaHash::Sha512),
|
|
||||||
_ => return Err(data_error("unsupported algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7.
|
|
||||||
if let Some(pk_hash) = pk_hash {
|
|
||||||
if pk_hash != hash {
|
|
||||||
return Err(data_error("hash mismatch"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8-9.
|
// 8-9.
|
||||||
|
@ -260,26 +238,9 @@ fn import_key_rsassa(
|
||||||
// 4-5.
|
// 4-5.
|
||||||
let alg = pk_info.algorithm.oid;
|
let alg = pk_info.algorithm.oid;
|
||||||
|
|
||||||
// 6.
|
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||||
let pk_hash = match alg {
|
if alg != RSA_ENCRYPTION_OID {
|
||||||
// rsaEncryption
|
return Err(data_error("unsupported algorithm"));
|
||||||
RSA_ENCRYPTION_OID => None,
|
|
||||||
// sha1WithRSAEncryption
|
|
||||||
SHA1_RSA_ENCRYPTION_OID => Some(ShaHash::Sha1),
|
|
||||||
// sha256WithRSAEncryption
|
|
||||||
SHA256_RSA_ENCRYPTION_OID => Some(ShaHash::Sha256),
|
|
||||||
// sha384WithRSAEncryption
|
|
||||||
SHA384_RSA_ENCRYPTION_OID => Some(ShaHash::Sha384),
|
|
||||||
// sha512WithRSAEncryption
|
|
||||||
SHA512_RSA_ENCRYPTION_OID => Some(ShaHash::Sha512),
|
|
||||||
_ => return Err(data_error("unsupported algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7.
|
|
||||||
if let Some(pk_hash) = pk_hash {
|
|
||||||
if pk_hash != hash {
|
|
||||||
return Err(data_error("hash mismatch"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8-9.
|
// 8-9.
|
||||||
|
@ -317,7 +278,6 @@ fn import_key_rsassa(
|
||||||
|
|
||||||
fn import_key_rsapss(
|
fn import_key_rsapss(
|
||||||
key_data: KeyData,
|
key_data: KeyData,
|
||||||
hash: ShaHash,
|
|
||||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||||
match key_data {
|
match key_data {
|
||||||
KeyData::Spki(data) => {
|
KeyData::Spki(data) => {
|
||||||
|
@ -328,47 +288,9 @@ fn import_key_rsapss(
|
||||||
// 4-5.
|
// 4-5.
|
||||||
let alg = pk_info.algorithm.oid;
|
let alg = pk_info.algorithm.oid;
|
||||||
|
|
||||||
// 6.
|
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||||
let pk_hash = match alg {
|
if alg != RSA_ENCRYPTION_OID {
|
||||||
// rsaEncryption
|
return Err(data_error("unsupported algorithm"));
|
||||||
RSA_ENCRYPTION_OID => None,
|
|
||||||
// id-RSASSA-PSS
|
|
||||||
RSASSA_PSS_OID => {
|
|
||||||
let params = PssPrivateKeyParameters::try_from(
|
|
||||||
pk_info
|
|
||||||
.algorithm
|
|
||||||
.parameters
|
|
||||||
.ok_or_else(|| data_error("malformed parameters"))?,
|
|
||||||
)
|
|
||||||
.map_err(|_| data_error("malformed parameters"))?;
|
|
||||||
|
|
||||||
let hash_alg = params.hash_algorithm;
|
|
||||||
let hash = match hash_alg.oid {
|
|
||||||
// id-sha1
|
|
||||||
ID_SHA1_OID => Some(ShaHash::Sha1),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA256_OID => Some(ShaHash::Sha256),
|
|
||||||
// id-sha384
|
|
||||||
ID_SHA384_OID => Some(ShaHash::Sha384),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA512_OID => Some(ShaHash::Sha512),
|
|
||||||
_ => return Err(data_error("unsupported hash algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
if params.mask_gen_algorithm.oid != ID_MFG1 {
|
|
||||||
return Err(not_supported_error("unsupported hash algorithm"));
|
|
||||||
}
|
|
||||||
|
|
||||||
hash
|
|
||||||
}
|
|
||||||
_ => return Err(data_error("unsupported algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7.
|
|
||||||
if let Some(pk_hash) = pk_hash {
|
|
||||||
if pk_hash != hash {
|
|
||||||
return Err(data_error("hash mismatch"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8-9.
|
// 8-9.
|
||||||
|
@ -405,42 +327,9 @@ fn import_key_rsapss(
|
||||||
// 4-5.
|
// 4-5.
|
||||||
let alg = pk_info.algorithm.oid;
|
let alg = pk_info.algorithm.oid;
|
||||||
|
|
||||||
// 6.
|
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||||
// 6.
|
if alg != RSA_ENCRYPTION_OID {
|
||||||
let pk_hash = match alg {
|
return Err(data_error("unsupported algorithm"));
|
||||||
// rsaEncryption
|
|
||||||
RSA_ENCRYPTION_OID => None,
|
|
||||||
// id-RSASSA-PSS
|
|
||||||
RSASSA_PSS_OID => {
|
|
||||||
let params = PssPrivateKeyParameters::try_from(
|
|
||||||
pk_info
|
|
||||||
.algorithm
|
|
||||||
.parameters
|
|
||||||
.ok_or_else(|| not_supported_error("malformed parameters"))?,
|
|
||||||
)
|
|
||||||
.map_err(|_| not_supported_error("malformed parameters"))?;
|
|
||||||
|
|
||||||
let hash_alg = params.hash_algorithm;
|
|
||||||
match hash_alg.oid {
|
|
||||||
// id-sha1
|
|
||||||
ID_SHA1_OID => Some(ShaHash::Sha1),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA256_OID => Some(ShaHash::Sha256),
|
|
||||||
// id-sha384
|
|
||||||
ID_SHA384_OID => Some(ShaHash::Sha384),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA512_OID => Some(ShaHash::Sha512),
|
|
||||||
_ => return Err(data_error("unsupported hash algorithm")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return Err(data_error("unsupported algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7.
|
|
||||||
if let Some(pk_hash) = pk_hash {
|
|
||||||
if pk_hash != hash {
|
|
||||||
return Err(data_error("hash mismatch"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8-9.
|
// 8-9.
|
||||||
|
@ -478,7 +367,6 @@ fn import_key_rsapss(
|
||||||
|
|
||||||
fn import_key_rsaoaep(
|
fn import_key_rsaoaep(
|
||||||
key_data: KeyData,
|
key_data: KeyData,
|
||||||
hash: ShaHash,
|
|
||||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||||
match key_data {
|
match key_data {
|
||||||
KeyData::Spki(data) => {
|
KeyData::Spki(data) => {
|
||||||
|
@ -489,41 +377,9 @@ fn import_key_rsaoaep(
|
||||||
// 4-5.
|
// 4-5.
|
||||||
let alg = pk_info.algorithm.oid;
|
let alg = pk_info.algorithm.oid;
|
||||||
|
|
||||||
// 6.
|
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||||
let pk_hash = match alg {
|
if alg != RSA_ENCRYPTION_OID {
|
||||||
// rsaEncryption
|
return Err(data_error("unsupported algorithm"));
|
||||||
RSA_ENCRYPTION_OID => None,
|
|
||||||
// id-RSAES-OAEP
|
|
||||||
RSAES_OAEP_OID => {
|
|
||||||
let params = OaepPrivateKeyParameters::try_from(
|
|
||||||
pk_info
|
|
||||||
.algorithm
|
|
||||||
.parameters
|
|
||||||
.ok_or_else(|| data_error("malformed parameters"))?,
|
|
||||||
)
|
|
||||||
.map_err(|_| data_error("malformed parameters"))?;
|
|
||||||
|
|
||||||
let hash_alg = params.hash_algorithm;
|
|
||||||
match hash_alg.oid {
|
|
||||||
// id-sha1
|
|
||||||
ID_SHA1_OID => Some(ShaHash::Sha1),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA256_OID => Some(ShaHash::Sha256),
|
|
||||||
// id-sha384
|
|
||||||
ID_SHA384_OID => Some(ShaHash::Sha384),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA512_OID => Some(ShaHash::Sha512),
|
|
||||||
_ => return Err(data_error("unsupported hash algorithm")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return Err(data_error("unsupported algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7.
|
|
||||||
if let Some(pk_hash) = pk_hash {
|
|
||||||
if pk_hash != hash {
|
|
||||||
return Err(data_error("hash mismatch"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8-9.
|
// 8-9.
|
||||||
|
@ -560,42 +416,9 @@ fn import_key_rsaoaep(
|
||||||
// 4-5.
|
// 4-5.
|
||||||
let alg = pk_info.algorithm.oid;
|
let alg = pk_info.algorithm.oid;
|
||||||
|
|
||||||
// 6.
|
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||||
// 6.
|
if alg != RSA_ENCRYPTION_OID {
|
||||||
let pk_hash = match alg {
|
return Err(data_error("unsupported algorithm"));
|
||||||
// rsaEncryption
|
|
||||||
RSA_ENCRYPTION_OID => None,
|
|
||||||
// id-RSAES-OAEP
|
|
||||||
RSAES_OAEP_OID => {
|
|
||||||
let params = OaepPrivateKeyParameters::try_from(
|
|
||||||
pk_info
|
|
||||||
.algorithm
|
|
||||||
.parameters
|
|
||||||
.ok_or_else(|| not_supported_error("malformed parameters"))?,
|
|
||||||
)
|
|
||||||
.map_err(|_| not_supported_error("malformed parameters"))?;
|
|
||||||
|
|
||||||
let hash_alg = params.hash_algorithm;
|
|
||||||
match hash_alg.oid {
|
|
||||||
// id-sha1
|
|
||||||
ID_SHA1_OID => Some(ShaHash::Sha1),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA256_OID => Some(ShaHash::Sha256),
|
|
||||||
// id-sha384
|
|
||||||
ID_SHA384_OID => Some(ShaHash::Sha384),
|
|
||||||
// id-sha256
|
|
||||||
ID_SHA512_OID => Some(ShaHash::Sha512),
|
|
||||||
_ => return Err(data_error("unsupported hash algorithm")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return Err(data_error("unsupported algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7.
|
|
||||||
if let Some(pk_hash) = pk_hash {
|
|
||||||
if pk_hash != hash {
|
|
||||||
return Err(data_error("hash mismatch"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8-9.
|
// 8-9.
|
||||||
|
|
|
@ -35,11 +35,8 @@ use ring::signature::EcdsaSigningAlgorithm;
|
||||||
use ring::signature::EcdsaVerificationAlgorithm;
|
use ring::signature::EcdsaVerificationAlgorithm;
|
||||||
use ring::signature::KeyPair;
|
use ring::signature::KeyPair;
|
||||||
use rsa::padding::PaddingScheme;
|
use rsa::padding::PaddingScheme;
|
||||||
use rsa::pkcs1::der::Decode;
|
|
||||||
use rsa::pkcs1::der::Encode;
|
|
||||||
use rsa::pkcs1::DecodeRsaPrivateKey;
|
use rsa::pkcs1::DecodeRsaPrivateKey;
|
||||||
use rsa::pkcs1::DecodeRsaPublicKey;
|
use rsa::pkcs1::DecodeRsaPublicKey;
|
||||||
use rsa::pkcs8::der::asn1;
|
|
||||||
use rsa::PublicKey;
|
use rsa::PublicKey;
|
||||||
use rsa::RsaPrivateKey;
|
use rsa::RsaPrivateKey;
|
||||||
use rsa::RsaPublicKey;
|
use rsa::RsaPublicKey;
|
||||||
|
@ -74,10 +71,6 @@ use crate::key::CryptoHash;
|
||||||
use crate::key::CryptoNamedCurve;
|
use crate::key::CryptoNamedCurve;
|
||||||
use crate::key::HkdfOutput;
|
use crate::key::HkdfOutput;
|
||||||
use crate::shared::RawKeyData;
|
use crate::shared::RawKeyData;
|
||||||
use crate::shared::ID_MFG1;
|
|
||||||
use crate::shared::ID_P_SPECIFIED;
|
|
||||||
use crate::shared::ID_SHA1_OID;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
pub fn init(maybe_seed: Option<u64>) -> Extension {
|
pub fn init(maybe_seed: Option<u64>) -> Extension {
|
||||||
Extension::builder()
|
Extension::builder()
|
||||||
|
@ -674,205 +667,6 @@ fn read_rsa_public_key(key_data: KeyData) -> Result<RsaPublicKey, AnyError> {
|
||||||
Ok(public_key)
|
Ok(public_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The parameters field associated with OID id-RSASSA-PSS
|
|
||||||
// Defined in RFC 3447, section A.2.3
|
|
||||||
//
|
|
||||||
// RSASSA-PSS-params ::= SEQUENCE {
|
|
||||||
// hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
|
|
||||||
// maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
|
|
||||||
// saltLength [2] INTEGER DEFAULT 20,
|
|
||||||
// trailerField [3] TrailerField DEFAULT trailerFieldBC
|
|
||||||
// }
|
|
||||||
pub struct PssPrivateKeyParameters<'a> {
|
|
||||||
pub hash_algorithm: rsa::pkcs8::AlgorithmIdentifier<'a>,
|
|
||||||
pub mask_gen_algorithm: rsa::pkcs8::AlgorithmIdentifier<'a>,
|
|
||||||
pub salt_length: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context-specific tag number for hashAlgorithm.
|
|
||||||
const HASH_ALGORITHM_TAG: rsa::pkcs8::der::TagNumber =
|
|
||||||
rsa::pkcs8::der::TagNumber::new(0);
|
|
||||||
|
|
||||||
// Context-specific tag number for maskGenAlgorithm.
|
|
||||||
const MASK_GEN_ALGORITHM_TAG: rsa::pkcs8::der::TagNumber =
|
|
||||||
rsa::pkcs8::der::TagNumber::new(1);
|
|
||||||
|
|
||||||
// Context-specific tag number for saltLength.
|
|
||||||
const SALT_LENGTH_TAG: rsa::pkcs8::der::TagNumber =
|
|
||||||
rsa::pkcs8::der::TagNumber::new(2);
|
|
||||||
|
|
||||||
// Context-specific tag number for pSourceAlgorithm
|
|
||||||
const P_SOURCE_ALGORITHM_TAG: rsa::pkcs8::der::TagNumber =
|
|
||||||
rsa::pkcs8::der::TagNumber::new(2);
|
|
||||||
|
|
||||||
// Default HashAlgorithm for RSASSA-PSS-params (sha1)
|
|
||||||
//
|
|
||||||
// sha1 HashAlgorithm ::= {
|
|
||||||
// algorithm id-sha1,
|
|
||||||
// parameters SHA1Parameters : NULL
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// SHA1Parameters ::= NULL
|
|
||||||
static SHA1_HASH_ALGORITHM: Lazy<rsa::pkcs8::AlgorithmIdentifier<'static>> =
|
|
||||||
Lazy::new(|| {
|
|
||||||
rsa::pkcs8::AlgorithmIdentifier {
|
|
||||||
// id-sha1
|
|
||||||
oid: ID_SHA1_OID,
|
|
||||||
// NULL
|
|
||||||
parameters: Some(asn1::AnyRef::from(asn1::Null)),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO(@littledivy): `pkcs8` should provide AlgorithmIdentifier to Any conversion.
|
|
||||||
static ENCODED_SHA1_HASH_ALGORITHM: Lazy<Vec<u8>> =
|
|
||||||
Lazy::new(|| SHA1_HASH_ALGORITHM.to_vec().unwrap());
|
|
||||||
// Default MaskGenAlgrithm for RSASSA-PSS-params (mgf1SHA1)
|
|
||||||
//
|
|
||||||
// mgf1SHA1 MaskGenAlgorithm ::= {
|
|
||||||
// algorithm id-mgf1,
|
|
||||||
// parameters HashAlgorithm : sha1
|
|
||||||
// }
|
|
||||||
static MGF1_SHA1_MASK_ALGORITHM: Lazy<
|
|
||||||
rsa::pkcs8::AlgorithmIdentifier<'static>,
|
|
||||||
> = Lazy::new(|| {
|
|
||||||
rsa::pkcs8::AlgorithmIdentifier {
|
|
||||||
// id-mgf1
|
|
||||||
oid: ID_MFG1,
|
|
||||||
// sha1
|
|
||||||
parameters: Some(
|
|
||||||
asn1::AnyRef::from_der(&ENCODED_SHA1_HASH_ALGORITHM).unwrap(),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Default PSourceAlgorithm for RSAES-OAEP-params
|
|
||||||
// The default label is an empty string.
|
|
||||||
//
|
|
||||||
// pSpecifiedEmpty PSourceAlgorithm ::= {
|
|
||||||
// algorithm id-pSpecified,
|
|
||||||
// parameters EncodingParameters : emptyString
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// emptyString EncodingParameters ::= ''H
|
|
||||||
static P_SPECIFIED_EMPTY: Lazy<rsa::pkcs8::AlgorithmIdentifier<'static>> =
|
|
||||||
Lazy::new(|| {
|
|
||||||
rsa::pkcs8::AlgorithmIdentifier {
|
|
||||||
// id-pSpecified
|
|
||||||
oid: ID_P_SPECIFIED,
|
|
||||||
// EncodingParameters
|
|
||||||
parameters: Some(asn1::AnyRef::from(
|
|
||||||
asn1::OctetStringRef::new(b"").unwrap(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fn decode_content_tag<'a, T>(
|
|
||||||
decoder: &mut rsa::pkcs8::der::SliceReader<'a>,
|
|
||||||
tag: rsa::pkcs8::der::TagNumber,
|
|
||||||
) -> rsa::pkcs8::der::Result<Option<T>>
|
|
||||||
where
|
|
||||||
T: rsa::pkcs8::der::Decode<'a>,
|
|
||||||
{
|
|
||||||
Ok(
|
|
||||||
rsa::pkcs8::der::asn1::ContextSpecific::<T>::decode_explicit(decoder, tag)?
|
|
||||||
.map(|field| field.value),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TryFrom<rsa::pkcs8::der::asn1::AnyRef<'a>>
|
|
||||||
for PssPrivateKeyParameters<'a>
|
|
||||||
{
|
|
||||||
type Error = rsa::pkcs8::der::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
any: rsa::pkcs8::der::asn1::AnyRef<'a>,
|
|
||||||
) -> rsa::pkcs8::der::Result<PssPrivateKeyParameters<'a>> {
|
|
||||||
any.sequence(|decoder| {
|
|
||||||
let hash_algorithm =
|
|
||||||
decode_content_tag::<rsa::pkcs8::AlgorithmIdentifier>(
|
|
||||||
decoder,
|
|
||||||
HASH_ALGORITHM_TAG,
|
|
||||||
)?
|
|
||||||
.map(TryInto::try_into)
|
|
||||||
.transpose()?
|
|
||||||
.unwrap_or(*SHA1_HASH_ALGORITHM);
|
|
||||||
|
|
||||||
let mask_gen_algorithm = decode_content_tag::<
|
|
||||||
rsa::pkcs8::AlgorithmIdentifier,
|
|
||||||
>(decoder, MASK_GEN_ALGORITHM_TAG)?
|
|
||||||
.map(TryInto::try_into)
|
|
||||||
.transpose()?
|
|
||||||
.unwrap_or(*MGF1_SHA1_MASK_ALGORITHM);
|
|
||||||
|
|
||||||
let salt_length = decode_content_tag::<u32>(decoder, SALT_LENGTH_TAG)?
|
|
||||||
.map(TryInto::try_into)
|
|
||||||
.transpose()?
|
|
||||||
.unwrap_or(20);
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
hash_algorithm,
|
|
||||||
mask_gen_algorithm,
|
|
||||||
salt_length,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The parameters field associated with OID id-RSAES-OAEP
|
|
||||||
// Defined in RFC 3447, section A.2.1
|
|
||||||
//
|
|
||||||
// RSAES-OAEP-params ::= SEQUENCE {
|
|
||||||
// hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
|
|
||||||
// maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
|
|
||||||
// pSourceAlgorithm [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty
|
|
||||||
// }
|
|
||||||
pub struct OaepPrivateKeyParameters<'a> {
|
|
||||||
pub hash_algorithm: rsa::pkcs8::AlgorithmIdentifier<'a>,
|
|
||||||
pub mask_gen_algorithm: rsa::pkcs8::AlgorithmIdentifier<'a>,
|
|
||||||
pub p_source_algorithm: rsa::pkcs8::AlgorithmIdentifier<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TryFrom<rsa::pkcs8::der::asn1::AnyRef<'a>>
|
|
||||||
for OaepPrivateKeyParameters<'a>
|
|
||||||
{
|
|
||||||
type Error = rsa::pkcs8::der::Error;
|
|
||||||
|
|
||||||
fn try_from(
|
|
||||||
any: rsa::pkcs8::der::asn1::AnyRef<'a>,
|
|
||||||
) -> rsa::pkcs8::der::Result<OaepPrivateKeyParameters<'a>> {
|
|
||||||
any.sequence(|decoder| {
|
|
||||||
let hash_algorithm =
|
|
||||||
decode_content_tag::<rsa::pkcs8::AlgorithmIdentifier>(
|
|
||||||
decoder,
|
|
||||||
HASH_ALGORITHM_TAG,
|
|
||||||
)?
|
|
||||||
.map(TryInto::try_into)
|
|
||||||
.transpose()?
|
|
||||||
.unwrap_or(*SHA1_HASH_ALGORITHM);
|
|
||||||
|
|
||||||
let mask_gen_algorithm = decode_content_tag::<
|
|
||||||
rsa::pkcs8::AlgorithmIdentifier,
|
|
||||||
>(decoder, MASK_GEN_ALGORITHM_TAG)?
|
|
||||||
.map(TryInto::try_into)
|
|
||||||
.transpose()?
|
|
||||||
.unwrap_or(*MGF1_SHA1_MASK_ALGORITHM);
|
|
||||||
|
|
||||||
let p_source_algorithm = decode_content_tag::<
|
|
||||||
rsa::pkcs8::AlgorithmIdentifier,
|
|
||||||
>(decoder, P_SOURCE_ALGORITHM_TAG)?
|
|
||||||
.map(TryInto::try_into)
|
|
||||||
.transpose()?
|
|
||||||
.unwrap_or(*P_SPECIFIED_EMPTY);
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
hash_algorithm,
|
|
||||||
mask_gen_algorithm,
|
|
||||||
p_source_algorithm,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
pub fn op_crypto_random_uuid(state: &mut OpState) -> Result<String, AnyError> {
|
pub fn op_crypto_random_uuid(state: &mut OpState) -> Result<String, AnyError> {
|
||||||
let maybe_seeded_rng = state.try_borrow_mut::<StdRng>();
|
let maybe_seeded_rng = state.try_borrow_mut::<StdRng>();
|
||||||
|
|
|
@ -14,30 +14,6 @@ use serde::Serialize;
|
||||||
|
|
||||||
pub const RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier =
|
pub const RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier =
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
|
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
|
||||||
pub const SHA1_RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5");
|
|
||||||
pub const SHA256_RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11");
|
|
||||||
pub const SHA384_RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12");
|
|
||||||
pub const SHA512_RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13");
|
|
||||||
pub const RSASSA_PSS_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10");
|
|
||||||
pub const ID_SHA1_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
|
|
||||||
pub const ID_SHA256_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.1");
|
|
||||||
pub const ID_SHA384_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.2");
|
|
||||||
pub const ID_SHA512_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.3");
|
|
||||||
pub const ID_MFG1: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8");
|
|
||||||
pub const RSAES_OAEP_OID: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.7");
|
|
||||||
pub const ID_P_SPECIFIED: const_oid::ObjectIdentifier =
|
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.9");
|
|
||||||
|
|
||||||
pub const ID_SECP256R1_OID: const_oid::ObjectIdentifier =
|
pub const ID_SECP256R1_OID: const_oid::ObjectIdentifier =
|
||||||
const_oid::ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7");
|
const_oid::ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7");
|
||||||
|
|
Loading…
Reference in a new issue