Key generation a signing for RSASHA512. (#659)

This commit is contained in:
Philip-NLnetLabs
2026-05-21 12:10:06 +02:00
committed by GitHub
parent f538651bf9
commit 80cf91e7d1
5 changed files with 148 additions and 23 deletions
+57 -16
View File
@@ -446,7 +446,8 @@ pub mod sign {
}
let pkey = match secret {
SecretKeyBytes::RsaSha256(s) => {
SecretKeyBytes::RsaSha256(s)
| SecretKeyBytes::RsaSha512(s) => {
let n = num(&s.n)?;
let e = num(&s.e)?;
@@ -458,12 +459,20 @@ pub mod sign {
.expect("should not fail");
let rsa_public =
PKey::from_rsa(rsa_public).expect("should not fail");
let p = PublicKey::Rsa(
MessageDigest::sha256(),
rsa_public,
public.flags(),
)
.dnskey();
let digest =
if matches!(secret, SecretKeyBytes::RsaSha256(_)) {
MessageDigest::sha256()
} else if matches!(
secret,
SecretKeyBytes::RsaSha512(_)
) {
MessageDigest::sha512()
} else {
unreachable!();
};
let p =
PublicKey::Rsa(digest, rsa_public, public.flags())
.dnskey();
if p != *public {
return Err(FromBytesError::InvalidKey);
}
@@ -585,9 +594,10 @@ pub mod sign {
pub fn to_bytes(&self) -> SecretKeyBytes {
// TODO: Consider security implications of secret data in 'Vec's.
match self.algorithm {
SecurityAlgorithm::RSASHA256 => {
SecurityAlgorithm::RSASHA256
| SecurityAlgorithm::RSASHA512 => {
let key = self.pkey.rsa().unwrap();
SecretKeyBytes::RsaSha256(RsaSecretKeyBytes {
let secret_key_bytes = RsaSecretKeyBytes {
n: key.n().to_vec().into(),
e: key.e().to_vec().into(),
d: key.d().to_vec().into(),
@@ -596,7 +606,14 @@ pub mod sign {
d_p: key.dmp1().unwrap().to_vec().into(),
d_q: key.dmq1().unwrap().to_vec().into(),
q_i: key.iqmp().unwrap().to_vec().into(),
})
};
if self.algorithm == SecurityAlgorithm::RSASHA256 {
SecretKeyBytes::RsaSha256(secret_key_bytes)
} else if self.algorithm == SecurityAlgorithm::RSASHA512 {
SecretKeyBytes::RsaSha512(secret_key_bytes)
} else {
unreachable!();
}
}
SecurityAlgorithm::ECDSAP256SHA256 => {
let key = self.pkey.ec_key().unwrap();
@@ -641,6 +658,13 @@ pub mod sign {
s.sign_oneshot_to_vec(data)
}
SecurityAlgorithm::RSASHA512 => {
let mut s =
Signer::new(MessageDigest::sha512(), &self.pkey)?;
s.set_rsa_padding(openssl::rsa::Padding::PKCS1)?;
s.sign_oneshot_to_vec(data)
}
SecurityAlgorithm::ECDSAP256SHA256 => {
let mut s =
Signer::new(MessageDigest::sha256(), &self.pkey)?;
@@ -687,18 +711,24 @@ pub mod sign {
fn dnskey(&self) -> Dnskey<Vec<u8>> {
match self.algorithm {
SecurityAlgorithm::RSASHA256 => {
SecurityAlgorithm::RSASHA256
| SecurityAlgorithm::RSASHA512 => {
let key = self.pkey.rsa().expect("should not fail");
let n = key.n().to_owned().expect("should not fail");
let e = key.e().to_owned().expect("should not fail");
let key = Rsa::from_public_components(n, e)
.expect("should not fail");
let key = PKey::from_rsa(key).expect("should not fail");
let public = PublicKey::Rsa(
MessageDigest::sha256(),
key,
self.flags,
);
let digest = if self.algorithm
== SecurityAlgorithm::RSASHA256
{
MessageDigest::sha256()
} else if self.algorithm == SecurityAlgorithm::RSASHA512 {
MessageDigest::sha512()
} else {
unreachable!();
};
let public = PublicKey::Rsa(digest, key, self.flags);
public.dnskey()
}
SecurityAlgorithm::ECDSAP256SHA256
@@ -756,6 +786,10 @@ pub mod sign {
Ok(Signature::RsaSha256(signature))
}
SecurityAlgorithm::RSASHA512 => {
Ok(Signature::RsaSha512(signature))
}
SecurityAlgorithm::ECDSAP256SHA256 => signature
.try_into()
.map(Signature::EcdsaP256Sha256)
@@ -827,6 +861,7 @@ pub mod sign {
const KEYS: &[(SecurityAlgorithm, u16)] = &[
(SecurityAlgorithm::RSASHA256, 60616),
(SecurityAlgorithm::RSASHA512, 46731),
(SecurityAlgorithm::ECDSAP256SHA256, 42253),
(SecurityAlgorithm::ECDSAP384SHA384, 33566),
(SecurityAlgorithm::ED25519, 56037),
@@ -840,6 +875,9 @@ pub mod sign {
SecurityAlgorithm::RSASHA256 => {
GenerateParams::RsaSha256 { bits: 3072 }
}
SecurityAlgorithm::RSASHA512 => {
GenerateParams::RsaSha512 { bits: 3072 }
}
SecurityAlgorithm::ECDSAP256SHA256 => {
GenerateParams::EcdsaP256Sha256
}
@@ -862,6 +900,9 @@ pub mod sign {
SecurityAlgorithm::RSASHA256 => {
GenerateParams::RsaSha256 { bits: 3072 }
}
SecurityAlgorithm::RSASHA512 => {
GenerateParams::RsaSha512 { bits: 3072 }
}
SecurityAlgorithm::ECDSAP256SHA256 => {
GenerateParams::EcdsaP256Sha256
}
+59 -7
View File
@@ -329,6 +329,18 @@ pub mod sign {
rng: Arc<dyn ring::rand::SecureRandom + Send + Sync>,
},
/// An RSA/SHA-512 keypair.
RsaSha512 {
/// They RSA key.
key: RsaKeyPair,
/// Flags from [`Dnskey`].
flags: u16,
/// Random number generator.
rng: Arc<dyn ring::rand::SecureRandom + Send + Sync>,
},
/// An ECDSA P-256/SHA-256 keypair.
EcdsaP256Sha256 {
/// The ECDSA key.
@@ -370,12 +382,20 @@ pub mod sign {
{
let rng = Arc::new(SystemRandom::new());
match secret {
SecretKeyBytes::RsaSha256(s) => {
SecretKeyBytes::RsaSha256(s)
| SecretKeyBytes::RsaSha512(s) => {
let rsa_public = signature::RsaPublicKeyComponents {
n: s.n.to_vec(),
e: s.e.to_vec(),
};
let p = PublicKey::Rsa(&signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, rsa_public).dnskey(public.flags());
let p = if matches!(secret, SecretKeyBytes::RsaSha256(_))
{
PublicKey::Rsa(&signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, rsa_public).dnskey(public.flags())
} else if matches!(secret, SecretKeyBytes::RsaSha512(_)) {
PublicKey::Rsa(&signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY, rsa_public).dnskey(public.flags())
} else {
unreachable!();
};
// Ensure that the public and private key match.
if p != *public {
return Err(FromBytesError::InvalidKey);
@@ -398,13 +418,26 @@ pub mod sign {
dQ: s.d_q.expose_secret(),
qInv: s.q_i.expose_secret(),
};
ring::signature::RsaKeyPair::from_components(&components)
.map_err(|_| FromBytesError::InvalidKey)
.map(|key| Self::RsaSha256 {
let key_pair =
ring::signature::RsaKeyPair::from_components(
&components,
)
.map_err(|_| FromBytesError::InvalidKey);
if matches!(secret, SecretKeyBytes::RsaSha256(_)) {
key_pair.map(|key| Self::RsaSha256 {
key,
flags: public.flags(),
rng,
})
} else if matches!(secret, SecretKeyBytes::RsaSha512(_)) {
key_pair.map(|key| Self::RsaSha512 {
key,
flags: public.flags(),
rng,
})
} else {
unreachable!();
}
}
SecretKeyBytes::EcdsaP256Sha256(s) => {
@@ -477,6 +510,7 @@ pub mod sign {
fn algorithm(&self) -> SecurityAlgorithm {
match self {
Self::RsaSha256 { .. } => SecurityAlgorithm::RSASHA256,
Self::RsaSha512 { .. } => SecurityAlgorithm::RSASHA512,
Self::EcdsaP256Sha256 { .. } => {
SecurityAlgorithm::ECDSAP256SHA256
}
@@ -489,14 +523,21 @@ pub mod sign {
fn dnskey(&self) -> Dnskey<Vec<u8>> {
match self {
Self::RsaSha256 { key, flags, rng: _ } => {
Self::RsaSha256 { key, flags, rng: _ }
| Self::RsaSha512 { key, flags, rng: _ } => {
let components: ring::rsa::PublicKeyComponents<Vec<u8>> =
key.public().into();
let n = components.n;
let e = components.e;
let public_key =
signature::RsaPublicKeyComponents { n, e };
let public = PublicKey::Rsa(&signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, public_key);
let public = if matches!(self, Self::RsaSha256 { .. }) {
PublicKey::Rsa(&signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, public_key)
} else if matches!(self, Self::RsaSha512 { .. }) {
PublicKey::Rsa(&signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY, public_key)
} else {
unreachable!();
};
public.dnskey(*flags)
}
@@ -563,6 +604,16 @@ pub mod sign {
.map_err(|_| SignError)
}
Self::RsaSha512 { key, flags: _, rng } => {
let mut buf = vec![0u8; key.public().modulus_len()];
let pad = &ring::signature::RSA_PKCS1_SHA512;
key.sign(pad, &**rng, data, &mut buf)
.map(|()| {
Signature::RsaSha512(buf.into_boxed_slice())
})
.map_err(|_| SignError)
}
Self::EcdsaP256Sha256 { key, flags: _, rng } => key
.sign(&**rng, data)
.map(|sig| Box::<[u8]>::from(sig.as_ref()))
@@ -689,6 +740,7 @@ pub mod sign {
const KEYS: &[(SecurityAlgorithm, u16)] = &[
(SecurityAlgorithm::RSASHA256, 60616),
(SecurityAlgorithm::RSASHA512, 46731),
(SecurityAlgorithm::ECDSAP256SHA256, 42253),
(SecurityAlgorithm::ECDSAP384SHA384, 33566),
(SecurityAlgorithm::ED25519, 56037),
+21
View File
@@ -520,6 +520,9 @@ pub enum SecretKeyBytes {
/// An RSA/SHA-256 keypair.
RsaSha256(RsaSecretKeyBytes),
/// An RSA/SHA-256 keypair.
RsaSha512(RsaSecretKeyBytes),
/// An ECDSA P-256/SHA-256 keypair.
///
/// The private key is a single 32-byte big-endian integer.
@@ -548,6 +551,7 @@ impl SecretKeyBytes {
pub fn algorithm(&self) -> SecurityAlgorithm {
match self {
Self::RsaSha256(_) => SecurityAlgorithm::RSASHA256,
Self::RsaSha512(_) => SecurityAlgorithm::RSASHA512,
Self::EcdsaP256Sha256(_) => SecurityAlgorithm::ECDSAP256SHA256,
Self::EcdsaP384Sha384(_) => SecurityAlgorithm::ECDSAP384SHA384,
Self::Ed25519(_) => SecurityAlgorithm::ED25519,
@@ -572,6 +576,11 @@ impl SecretKeyBytes {
k.format_as_bind(w)
}
Self::RsaSha512(k) => {
writeln!(w, "Algorithm: 10 (RSASHA512)")?;
k.format_as_bind(w)
}
Self::EcdsaP256Sha256(s) => {
let s = s.expose_secret();
writeln!(w, "Algorithm: 13 (ECDSAP256SHA256)")?;
@@ -675,6 +684,9 @@ impl SecretKeyBytes {
(8, "(RSASHA256)") => {
RsaSecretKeyBytes::parse_from_bind(data).map(Self::RsaSha256)
}
(10, "(RSASHA512)") => {
RsaSecretKeyBytes::parse_from_bind(data).map(Self::RsaSha512)
}
(13, "(ECDSAP256SHA256)") => {
parse_pkey(data).map(Self::EcdsaP256Sha256)
}
@@ -1094,6 +1106,7 @@ mod tests {
};
const KEYS: &[(SecurityAlgorithm, u16)] = &[
(SecurityAlgorithm::RSASHA256, 60616),
(SecurityAlgorithm::RSASHA512, 46731),
(SecurityAlgorithm::ECDSAP256SHA256, 42253),
(SecurityAlgorithm::ECDSAP384SHA384, 33566),
(SecurityAlgorithm::ED25519, 56037),
@@ -1139,6 +1152,14 @@ mod tests {
continue;
}
}
SecurityAlgorithm::RSASHA512 => {
if cfg!(feature = "openssl") {
GenerateParams::RsaSha512 { bits: 2048 }
} else {
// No support for RSASHA256 in Ring.
continue;
}
}
SecurityAlgorithm::ECDSAP256SHA256 => {
GenerateParams::EcdsaP256Sha256
}
@@ -0,0 +1 @@
test. IN DNSKEY 256 3 10 AwEAAaOjLFFjqsv8lg/FBU8LCktei3/t3+C+s42cxmUOv4xvI/NPZ35i5zqTIoi4v0+EthzbcfnDvqVPdM1MRlVYRcWewuc18rrUZB6k1+igzcj5XuuilktNkHFfBOWinEYqzv/0KDuUSk5eMVG11DEQXx7qRPjH74WJ96sBcXzXm+GEcaYXXn/forV2khWtlGxDC6I9J6Zcwf8ACk5t6yiNBmvoljNR201clsgAgg7t+52X+echuEmkAybwVtL73tFw9JUnUeBA9Pm0pvq8hTNPXs/XhCnMw1wVRyECleOvBt2lx7s3suXXOljPdgjFZZTO2Mij8I3aYAafUEBzjcYssSU= ;{id = 46731 (zsk), size = 2048b}
@@ -0,0 +1,10 @@
Private-key-format: v1.2
Algorithm: 10 (RSASHA512)
Modulus: o6MsUWOqy/yWD8UFTwsKS16Lf+3f4L6zjZzGZQ6/jG8j809nfmLnOpMiiLi/T4S2HNtx+cO+pU90zUxGVVhFxZ7C5zXyutRkHqTX6KDNyPle66KWS02QcV8E5aKcRirO//QoO5RKTl4xUbXUMRBfHupE+MfvhYn3qwFxfNeb4YRxphdef9+itXaSFa2UbEMLoj0nplzB/wAKTm3rKI0Ga+iWM1HbTVyWyACCDu37nZf55yG4SaQDJvBW0vve0XD0lSdR4ED0+bSm+ryFM09ez9eEKczDXBVHIQKV468G3aXHuzey5dc6WM92CMVllM7YyKPwjdpgBp9QQHONxiyxJQ==
PublicExponent: AQAB
PrivateExponent: Bzb3CcGcsrC4xwo3QTRp6EfLW8EXqVePIBPE9YiwblcqHRynof1nV4BMOf33RWDDDMOqI0p7mdtGeZS+1x10uhFVY49P2+foYCeBc3q/h/hitH3vJXPOhgkb9Kn2POu/Q662pWXU3t6tSv561Az2PK00jEl4aIlcN5hxMgFpmIhFt8/oeT+4Z/h9N66jBM1e6z8TqM6jkqyJQ96hEtElDw+hZyxL84qJcfqPAraADJh1M9J5VzAauFhcKZ2LeUaDcb2DNiWhgMAbW7gfvx9QB58udavUSSAA3iqxo3aIMqvYqbxPnKb5KGvpNRTERgNPgNuF9Elzs2/6QNCyuYSYww==
Prime1: 5KIn8oSsNA22EJvzhWq0Hx+jMI4bPvGOrBfmD42FKvClPtA1sAMqsabQrE2t0lYzRBnHa7ad/TpQRBTFsydy8IFTHEDeISxo3Dch8Hr+Q474TCNTEHduX3pkniTZMMdzkcC9jD9d4NGKufMz57DVejoCjEao0ZyD/WATjGd1OCM=
Prime2: tzlkY2ryyYncIZlHtPP374MWzmUWSZHimZTDOP3Al6R87q7uWoa1G518049p//v/PZiT6rR5QFBgxS3H3B7Dhc4Ew8MED1lyO71+AvTpY/8/VsgIkJDnDKtOpY7jr/jd4avk7Ga4n+IpnNrJaLxGfcXHjJs8Xb2MiIpDbe0QIhc=
Exponent1: jmpvxcJc3gPYcBoko+umjWiQp3Mth5TCUXKFjRSTaf8Cf9EEUEJ4urZ1b47ngojNYFNKhE75tL45N19VEta04xk7ovLJKxLVsq7pBjom3gBVrF+ooy4x42mC+XtsitUCqTzNFWp3WM5Nwqy6nUzqfTtbUPPGvuLm2NKa+q+LNc8=
Exponent2: lf/pXK7QxwgS7HrFRrI4t5+1SxFc9qv1PFCapoyvYDYshWc3AWuo10vORpDxcb1HT5Ea/5nybiGfp618IowY+/EW24FLUJmkuJ3AjQEeFVyA6TXoNRo73ZZdU5Kwen8ef0Mvrg3GdjY8ZQqEuzbv6sXBQS5RdFjatWmkHFlozM8=
Coefficient: S/x4RWc2cB8lR4rn14cvah+lwo+opkyoumRxfoUqWKILxvMA2hRwhMtB90dP7TxzdN3VqmXZ4m4ygWEAKgrtXC1qhzKnXPJjWAgn/ElmsuVdW7azCexNN1PZxFRNIwLElrbTlLur/C9SvBBUtlUA2Z965mqjWMgd9ooYxjn3B44=