summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWiktor Kwapisiewicz <wiktor@metacode.biz>2022-08-10 13:23:45 +0200
committerWiktor Kwapisiewicz <wiktor@metacode.biz>2022-08-16 11:04:43 +0200
commitc4e6642f01ff45bfa4eea027b31c5418bfebb8b3 (patch)
treedda7a81febbfed9bed64f374c08b355656a6edca
parent3a3f59cc84acb2dd10c623c046201046ed6ea163 (diff)
openpgp: Expose `HashAlgorithm::oid()` on all crypto backends.
- Expose `oid()` function for all cryptographic backends. - Fix the description to accurately describe the bytes that are being returned. - Add the reference and note to the common use of this function. - Add practical example of computing the entire `DigestInfo` structure. - Add mention of the change to the NEWS file. - Add test case to check if the values match what Nettle is using. - Fixes #919.
-rw-r--r--openpgp/NEWS2
-rw-r--r--openpgp/src/crypto/backend/nettle/hash.rs28
-rw-r--r--openpgp/src/crypto/hash.rs81
3 files changed, 97 insertions, 14 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS
index 1a4ec42d..53b443b3 100644
--- a/openpgp/NEWS
+++ b/openpgp/NEWS
@@ -16,6 +16,8 @@
alternate formatter (e.g. =format!("{:#}", ...)=)
- cert::KeyBuilder
- cert::SubkeyBuilder
+ - HashAlgorithm::oid is available on all crypto backends
+ (previously only on Nettle)
** Deprecated functionality
- Error::UnsupportedCert, use Error::UnsupportedCert2 instead
- DataFormat::MIME, no replacement, see #863 for details
diff --git a/openpgp/src/crypto/backend/nettle/hash.rs b/openpgp/src/crypto/backend/nettle/hash.rs
index 925ff855..4bf1535e 100644
--- a/openpgp/src/crypto/backend/nettle/hash.rs
+++ b/openpgp/src/crypto/backend/nettle/hash.rs
@@ -78,21 +78,21 @@ impl HashAlgorithm {
Err(Error::UnsupportedHashAlgorithm(self).into()),
}
}
+}
- /// Returns the ASN.1 OID of this hash algorithm.
- pub fn oid(self) -> Result<&'static [u8]> {
- use nettle::rsa;
+#[cfg(all(test, feature = "crypto-nettle"))]
+mod tests {
+ use super::*;
+ use nettle::rsa;
- match self {
- HashAlgorithm::SHA1 => Ok(rsa::ASN1_OID_SHA1),
- HashAlgorithm::SHA224 => Ok(rsa::ASN1_OID_SHA224),
- HashAlgorithm::SHA256 => Ok(rsa::ASN1_OID_SHA256),
- HashAlgorithm::SHA384 => Ok(rsa::ASN1_OID_SHA384),
- HashAlgorithm::SHA512 => Ok(rsa::ASN1_OID_SHA512),
- HashAlgorithm::MD5 => Ok(rsa::ASN1_OID_MD5),
- HashAlgorithm::RipeMD => Ok(rsa::ASN1_OID_RIPEMD160),
- HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) =>
- Err(Error::UnsupportedHashAlgorithm(self).into()),
- }
+ #[test]
+ fn oids_match_nettle() {
+ assert_eq!(HashAlgorithm::SHA1.oid().unwrap(), rsa::ASN1_OID_SHA1);
+ assert_eq!(HashAlgorithm::SHA224.oid().unwrap(), rsa::ASN1_OID_SHA224);
+ assert_eq!(HashAlgorithm::SHA256.oid().unwrap(), rsa::ASN1_OID_SHA256);
+ assert_eq!(HashAlgorithm::SHA384.oid().unwrap(), rsa::ASN1_OID_SHA384);
+ assert_eq!(HashAlgorithm::SHA512.oid().unwrap(), rsa::ASN1_OID_SHA512);
+ assert_eq!(HashAlgorithm::MD5.oid().unwrap(), rsa::ASN1_OID_MD5);
+ assert_eq!(HashAlgorithm::RipeMD.oid().unwrap(), rsa::ASN1_OID_RIPEMD160);
}
}
diff --git a/openpgp/src/crypto/hash.rs b/openpgp/src/crypto/hash.rs
index 65c13ef9..9af3de07 100644
--- a/openpgp/src/crypto/hash.rs
+++ b/openpgp/src/crypto/hash.rs
@@ -51,6 +51,51 @@ use std::io::{self, Write};
// hashed to files /tmp/hash-N, where N is a number.
const DUMP_HASHED_VALUES: Option<&str> = None;
+// ASN.1 OID values copied from the nettle-rs crate:
+// https://gitlab.com/sequoia-pgp/nettle-rs/-/blob/main/src/rsa/pkcs1.rs#L22
+
+/// ASN.1 OID for MD5
+const ASN1_OID_MD5: &[u8] = &[
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00, 0x04, 0x10,
+];
+
+/// ASN.1 OID for RipeMD160
+const ASN1_OID_RIPEMD160: &[u8] = &[
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05,
+ 0x00, 0x04, 0x14,
+];
+
+/// ASN.1 OID for SHA1
+const ASN1_OID_SHA1: &[u8] = &[
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14,
+];
+
+/// ASN.1 OID for SHA224
+const ASN1_OID_SHA224: &[u8] = &[
+ 0x30, 0x2D, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C,
+];
+
+/// ASN.1 OID for SHA256
+const ASN1_OID_SHA256: &[u8] = &[
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
+];
+
+/// ASN.1 OID for SHA384
+const ASN1_OID_SHA384: &[u8] = &[
+ 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30,
+];
+
+/// ASN.1 OID for SHA512
+const ASN1_OID_SHA512: &[u8] = &[
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x03, 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
@@ -159,6 +204,42 @@ impl HashAlgorithm {
hasher
})
}
+
+ /// Returns the prefix of a serialized `DigestInfo` structure
+ /// that contains the ASN.1 OID of this hash algorithm.
+ ///
+ /// The prefix is used for encoding RSA signatures according to
+ /// the `EMSA-PKCS1-v1_5` algorithm as specified in [RFC 8017].
+ ///
+ /// [RFC 8017]: https://www.rfc-editor.org/rfc/rfc8017.html#section-9.2
+ ///
+ /// ```
+ /// # use sequoia_openpgp::types::HashAlgorithm;
+ /// # fn main() -> sequoia_openpgp::Result<()> {
+ /// let algo = HashAlgorithm::SHA512;
+ /// let digest = // raw bytes of the digest
+ /// # Vec::<u8>::new();
+ /// let digest_info = Vec::from(algo.oid()?).extend(digest);
+ /// # Ok(()) }
+ /// ```
+ ///
+ /// # Errors
+ ///
+ /// Fails with `Error::UnsupportedHashAlgorithm` for unknown or
+ /// private hash algorithms.
+ pub fn oid(self) -> Result<&'static [u8]> {
+ match self {
+ HashAlgorithm::SHA1 => Ok(ASN1_OID_SHA1),
+ HashAlgorithm::SHA224 => Ok(ASN1_OID_SHA224),
+ HashAlgorithm::SHA256 => Ok(ASN1_OID_SHA256),
+ HashAlgorithm::SHA384 => Ok(ASN1_OID_SHA384),
+ HashAlgorithm::SHA512 => Ok(ASN1_OID_SHA512),
+ HashAlgorithm::MD5 => Ok(ASN1_OID_MD5),
+ HashAlgorithm::RipeMD => Ok(ASN1_OID_RIPEMD160),
+ HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) =>
+ Err(crate::Error::UnsupportedHashAlgorithm(self).into()),
+ }
+ }
}
struct HashDumper {