diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-06-22 13:07:40 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2024-06-20 10:58:42 +0200 |
commit | d460b086e284d66139e561457176790ddedc296f (patch) | |
tree | 7269c3948d7c5690df5623d48d88aa9d72d1a483 /openpgp/src | |
parent | 569423f718cfcf21d677541cf3553dddd502ec9a (diff) |
openpgp: Implement SHA3.
- CNG doesn't currently implement this on commonly deployed
installations. As this is not a high priority algorithm,
we don't implement it using RustCrypto when the CNG backend is
selected, but simply signal no support.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/crypto/backend/botan/hash.rs | 4 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng/hash.rs | 11 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/hash.rs | 8 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl/hash.rs | 2 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust/hash.rs | 6 | ||||
-rw-r--r-- | openpgp/src/crypto/hash.rs | 14 | ||||
-rw-r--r-- | openpgp/src/policy.rs | 10 | ||||
-rw-r--r-- | openpgp/src/types/mod.rs | 20 |
8 files changed, 71 insertions, 4 deletions
diff --git a/openpgp/src/crypto/backend/botan/hash.rs b/openpgp/src/crypto/backend/botan/hash.rs index 0e02b5dd..7f5934e3 100644 --- a/openpgp/src/crypto/backend/botan/hash.rs +++ b/openpgp/src/crypto/backend/botan/hash.rs @@ -48,6 +48,8 @@ impl HashAlgorithm { HashAlgorithm::SHA256 => true, HashAlgorithm::SHA384 => true, HashAlgorithm::SHA512 => true, + HashAlgorithm::SHA3_256 => true, + HashAlgorithm::SHA3_512 => true, HashAlgorithm::RipeMD => true, HashAlgorithm::MD5 => true, HashAlgorithm::Private(_) => false, @@ -82,6 +84,8 @@ impl HashAlgorithm { HashAlgorithm::SHA256 => Ok("SHA-256"), HashAlgorithm::SHA384 => Ok("SHA-384"), HashAlgorithm::SHA512 => Ok("SHA-512"), + HashAlgorithm::SHA3_256 => Ok("SHA-3(256)"), + HashAlgorithm::SHA3_512 => Ok("SHA-3(512)"), HashAlgorithm::MD5 => Ok("MD5"), HashAlgorithm::RipeMD => Ok("RIPEMD-160"), HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) => diff --git a/openpgp/src/crypto/backend/cng/hash.rs b/openpgp/src/crypto/backend/cng/hash.rs index 301ac0c6..e71789d1 100644 --- a/openpgp/src/crypto/backend/cng/hash.rs +++ b/openpgp/src/crypto/backend/cng/hash.rs @@ -84,6 +84,12 @@ impl TryFrom<HashAlgorithm> for cng::HashAlgorithmId { HashAlgorithm::SHA512 => cng::HashAlgorithmId::Sha512, HashAlgorithm::MD5 => cng::HashAlgorithmId::Md5, + // SHA3 support is on the horizon, see + // https://blogs.windows.com/windows-insider/2023/03/23/announcing-windows-11-insider-preview-build-25324/ + HashAlgorithm::SHA3_256 | + HashAlgorithm::SHA3_512 => + return Err(Error::UnsupportedHashAlgorithm(value)), + HashAlgorithm::SHA224 | HashAlgorithm::RipeMD | HashAlgorithm::Private(_) | @@ -119,6 +125,11 @@ impl HashAlgorithm { HashAlgorithm::SHA512 => true, HashAlgorithm::MD5 => true, + // SHA3 support is on the horizon, see + // https://blogs.windows.com/windows-insider/2023/03/23/announcing-windows-11-insider-preview-build-25324/ + HashAlgorithm::SHA3_256 | + HashAlgorithm::SHA3_512 => false, + HashAlgorithm::SHA224 | HashAlgorithm::RipeMD | HashAlgorithm::Private(_) | diff --git a/openpgp/src/crypto/backend/nettle/hash.rs b/openpgp/src/crypto/backend/nettle/hash.rs index 4bf1535e..3e9d12a6 100644 --- a/openpgp/src/crypto/backend/nettle/hash.rs +++ b/openpgp/src/crypto/backend/nettle/hash.rs @@ -29,6 +29,8 @@ impl_digest_for!(nettle::hash::Sha224, SHA224); impl_digest_for!(nettle::hash::Sha256, SHA256); impl_digest_for!(nettle::hash::Sha384, SHA384); impl_digest_for!(nettle::hash::Sha512, SHA512); +impl_digest_for!(nettle::hash::Sha3_256, SHA3_256); +impl_digest_for!(nettle::hash::Sha3_512, SHA3_512); impl_digest_for!(nettle::hash::insecure_do_not_use::Sha1, SHA1); impl_digest_for!(nettle::hash::insecure_do_not_use::Md5, MD5); impl_digest_for!(nettle::hash::insecure_do_not_use::Ripemd160, RipeMD); @@ -42,6 +44,8 @@ impl HashAlgorithm { HashAlgorithm::SHA256 => true, HashAlgorithm::SHA384 => true, HashAlgorithm::SHA512 => true, + HashAlgorithm::SHA3_256 => true, + HashAlgorithm::SHA3_512 => true, HashAlgorithm::RipeMD => true, HashAlgorithm::MD5 => true, HashAlgorithm::Private(_) => false, @@ -59,7 +63,7 @@ impl HashAlgorithm { /// /// [`HashAlgorithm::is_supported`]: HashAlgorithm::is_supported() pub(crate) fn new_hasher(self) -> Result<Box<dyn Digest>> { - use nettle::hash::{Sha224, Sha256, Sha384, Sha512}; + use nettle::hash::{Sha224, Sha256, Sha384, Sha512, Sha3_256, Sha3_512}; use nettle::hash::insecure_do_not_use::{ Sha1, Md5, @@ -72,6 +76,8 @@ impl HashAlgorithm { HashAlgorithm::SHA256 => Ok(Box::new(Sha256::default())), HashAlgorithm::SHA384 => Ok(Box::new(Sha384::default())), HashAlgorithm::SHA512 => Ok(Box::new(Sha512::default())), + HashAlgorithm::SHA3_256 => Ok(Box::new(Sha3_256::default())), + HashAlgorithm::SHA3_512 => Ok(Box::new(Sha3_512::default())), HashAlgorithm::MD5 => Ok(Box::new(Md5::default())), HashAlgorithm::RipeMD => Ok(Box::new(Ripemd160::default())), HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) => diff --git a/openpgp/src/crypto/backend/openssl/hash.rs b/openpgp/src/crypto/backend/openssl/hash.rs index b4f6d816..e8db9373 100644 --- a/openpgp/src/crypto/backend/openssl/hash.rs +++ b/openpgp/src/crypto/backend/openssl/hash.rs @@ -73,6 +73,8 @@ fn get_md(algo: HashAlgorithm) -> Option<MessageDigest> { SHA384 => Nid::SHA384, SHA512 => Nid::SHA512, SHA224 => Nid::SHA224, + SHA3_256 => Nid::SHA3_256, + SHA3_512 => Nid::SHA3_512, HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) => return None, }; diff --git a/openpgp/src/crypto/backend/rust/hash.rs b/openpgp/src/crypto/backend/rust/hash.rs index 069dfc79..ed3a3704 100644 --- a/openpgp/src/crypto/backend/rust/hash.rs +++ b/openpgp/src/crypto/backend/rust/hash.rs @@ -37,6 +37,8 @@ impl_digest_for!(sha2::Sha224, SHA224); impl_digest_for!(sha2::Sha256, SHA256); impl_digest_for!(sha2::Sha384, SHA384); impl_digest_for!(sha2::Sha512, SHA512); +impl_digest_for!(sha3::Sha3_256, SHA3_256); +impl_digest_for!(sha3::Sha3_512, SHA3_512); impl HashAlgorithm { /// Whether Sequoia supports this algorithm. @@ -47,6 +49,8 @@ impl HashAlgorithm { HashAlgorithm::SHA256 => true, HashAlgorithm::SHA384 => true, HashAlgorithm::SHA512 => true, + HashAlgorithm::SHA3_256 => true, + HashAlgorithm::SHA3_512 => true, HashAlgorithm::RipeMD => true, HashAlgorithm::MD5 => true, HashAlgorithm::Private(_) => false, @@ -73,6 +77,8 @@ impl HashAlgorithm { HashAlgorithm::SHA256 => Ok(Box::new(sha2::Sha256::new())), HashAlgorithm::SHA384 => Ok(Box::new(sha2::Sha384::new())), HashAlgorithm::SHA512 => Ok(Box::new(sha2::Sha512::new())), + HashAlgorithm::SHA3_256 => Ok(Box::new(sha3::Sha3_256::new())), + HashAlgorithm::SHA3_512 => Ok(Box::new(sha3::Sha3_512::new())), HashAlgorithm::RipeMD => Ok(Box::new(ripemd::Ripemd160::new())), HashAlgorithm::MD5 => Ok(Box::new(md5::Md5::new())), HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) => diff --git a/openpgp/src/crypto/hash.rs b/openpgp/src/crypto/hash.rs index e0e4fcd2..88676eba 100644 --- a/openpgp/src/crypto/hash.rs +++ b/openpgp/src/crypto/hash.rs @@ -96,6 +96,18 @@ const ASN1_OID_SHA512: &[u8] = &[ 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40, ]; +/// ASN.1 OID for SHA3-256 +const ASN1_OID_SHA3_256: &[u8] = &[ + 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20 +]; + +/// ASN.1 OID for SHA3-512. +const ASN1_OID_SHA3_512: &[u8] = &[ + 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40 +]; + lazy_static::lazy_static! { /// List of hashes that the signer may produce. /// This list is ordered by the preference so that the most preferred @@ -234,6 +246,8 @@ impl HashAlgorithm { HashAlgorithm::SHA256 => Ok(ASN1_OID_SHA256), HashAlgorithm::SHA384 => Ok(ASN1_OID_SHA384), HashAlgorithm::SHA512 => Ok(ASN1_OID_SHA512), + HashAlgorithm::SHA3_256 => Ok(ASN1_OID_SHA3_256), + HashAlgorithm::SHA3_512 => Ok(ASN1_OID_SHA3_512), HashAlgorithm::MD5 => Ok(ASN1_OID_MD5), HashAlgorithm::RipeMD => Ok(ASN1_OID_RIPEMD160), HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) => diff --git a/openpgp/src/policy.rs b/openpgp/src/policy.rs index d358ea69..03f67339 100644 --- a/openpgp/src/policy.rs +++ b/openpgp/src/policy.rs @@ -626,7 +626,7 @@ impl<'a> From<&'a StandardPolicy<'a>> for Option<&'a dyn Policy> { // Signatures that require a hash with collision Resistance and second // Pre-image Resistance. See the documentation for HashAlgoSecurity // for more details. -a_cutoff_list!(CollisionResistantHashCutoffList, HashAlgorithm, 12, +a_cutoff_list!(CollisionResistantHashCutoffList, HashAlgorithm, 15, [ REJECT, // 0. Not assigned. Some(Timestamp::Y1997M2), // 1. MD5 @@ -640,11 +640,14 @@ a_cutoff_list!(CollisionResistantHashCutoffList, HashAlgorithm, 12, ACCEPT, // 9. SHA384 ACCEPT, // 10. SHA512 ACCEPT, // 11. SHA224 + ACCEPT, // 12. SHA3-256 + REJECT, // 13. Reserved. + ACCEPT, // 14. SHA3-512 ]); // Signatures that *only* require a hash with Second Pre-image // Resistance. See the documentation for HashAlgoSecurity for more // details. -a_cutoff_list!(SecondPreImageResistantHashCutoffList, HashAlgorithm, 12, +a_cutoff_list!(SecondPreImageResistantHashCutoffList, HashAlgorithm, 15, [ REJECT, // 0. Not assigned. Some(Timestamp::Y2004M2), // 1. MD5 @@ -658,6 +661,9 @@ a_cutoff_list!(SecondPreImageResistantHashCutoffList, HashAlgorithm, 12, ACCEPT, // 9. SHA384 ACCEPT, // 10. SHA512 ACCEPT, // 11. SHA224 + ACCEPT, // 12. SHA3-256 + REJECT, // 13. Reserved. + ACCEPT, // 14. SHA3-512 ]); a_cutoff_list!(SubpacketTagCutoffList, SubpacketTag, 38, diff --git a/openpgp/src/types/mod.rs b/openpgp/src/types/mod.rs index b57b7669..2693df7a 100644 --- a/openpgp/src/types/mod.rs +++ b/openpgp/src/types/mod.rs @@ -1338,6 +1338,10 @@ pub enum HashAlgorithm { SHA512, /// 224-bit version of SHA2 SHA224, + /// 256-bit version of SHA3 + SHA3_256, + /// 512-bit version of SHA3 + SHA3_512, /// Private hash algorithm identifier. Private(u8), /// Unknown hash algorithm identifier. @@ -1345,7 +1349,7 @@ pub enum HashAlgorithm { } assert_send_and_sync!(HashAlgorithm); -const HASH_ALGORITHM_VARIANTS: [HashAlgorithm; 7] = [ +const HASH_ALGORITHM_VARIANTS: [HashAlgorithm; 9] = [ HashAlgorithm::MD5, HashAlgorithm::SHA1, HashAlgorithm::RipeMD, @@ -1353,6 +1357,8 @@ const HASH_ALGORITHM_VARIANTS: [HashAlgorithm; 7] = [ HashAlgorithm::SHA384, HashAlgorithm::SHA512, HashAlgorithm::SHA224, + HashAlgorithm::SHA3_256, + HashAlgorithm::SHA3_512, ]; impl Default for HashAlgorithm { @@ -1373,6 +1379,8 @@ impl From<u8> for HashAlgorithm { 9 => HashAlgorithm::SHA384, 10 => HashAlgorithm::SHA512, 11 => HashAlgorithm::SHA224, + 12 => HashAlgorithm::SHA3_256, + 14 => HashAlgorithm::SHA3_512, 100..=110 => HashAlgorithm::Private(u), u => HashAlgorithm::Unknown(u), } @@ -1389,6 +1397,8 @@ impl From<HashAlgorithm> for u8 { HashAlgorithm::SHA384 => 9, HashAlgorithm::SHA512 => 10, HashAlgorithm::SHA224 => 11, + HashAlgorithm::SHA3_256 => 12, + HashAlgorithm::SHA3_512 => 14, HashAlgorithm::Private(u) => u, HashAlgorithm::Unknown(u) => u, } @@ -1413,6 +1423,10 @@ impl FromStr for HashAlgorithm { Ok(HashAlgorithm::SHA512) } else if s.eq_ignore_ascii_case("SHA224") { Ok(HashAlgorithm::SHA224) + } else if s.eq_ignore_ascii_case("SHA3-256") { + Ok(HashAlgorithm::SHA3_256) + } else if s.eq_ignore_ascii_case("SHA3-512") { + Ok(HashAlgorithm::SHA3_512) } else { Err(()) } @@ -1429,6 +1443,8 @@ impl fmt::Display for HashAlgorithm { HashAlgorithm::SHA384 => f.write_str("SHA384"), HashAlgorithm::SHA512 => f.write_str("SHA512"), HashAlgorithm::SHA224 => f.write_str("SHA224"), + HashAlgorithm::SHA3_256 => f.write_str("SHA3-256"), + HashAlgorithm::SHA3_512 => f.write_str("SHA3-512"), HashAlgorithm::Private(u) => f.write_fmt(format_args!("Private/Experimental hash algorithm {}", u)), HashAlgorithm::Unknown(u) => @@ -1465,6 +1481,8 @@ impl HashAlgorithm { HashAlgorithm::SHA384 => Ok("SHA384"), HashAlgorithm::SHA512 => Ok("SHA512"), HashAlgorithm::SHA224 => Ok("SHA224"), + HashAlgorithm::SHA3_256 => Ok("SHA3-256"), + HashAlgorithm::SHA3_512 => Ok("SHA3-512"), HashAlgorithm::Private(_) => Err(Error::UnsupportedHashAlgorithm(*self).into()), HashAlgorithm::Unknown(_) => |