1use std::{
4 borrow::{Borrow, Cow},
5 collections::HashSet,
6 fmt::{Debug, Display},
7 str::FromStr,
8};
9
10use base64ct::{Base64, Encoding as _};
11use chrono::{DateTime, Utc};
12use email_address::{EmailAddress, Options};
13use log::error;
14use pgp::{
15 ArmorOptions,
16 Deserializable,
17 KeyDetails,
18 SignedPublicKey,
19 SignedSecretKey,
20 StandaloneSignature,
21 crypto::{ecc_curve::ECCCurve, hash::HashAlgorithm, public_key::PublicKeyAlgorithm},
22 packet::{
23 KeyFlags,
24 Notation,
25 PublicKey,
26 SignatureConfig,
27 SignatureType,
28 Subpacket,
29 SubpacketData,
30 UserId,
31 },
32 ser::Serialize,
33 types::{
34 CompressionAlgorithm,
35 EcdsaPublicParams,
36 EskType,
37 KeyId,
38 KeyVersion,
39 Mpi,
40 PkeskBytes,
41 PlainSecretParams,
42 PublicKeyTrait,
43 PublicParams,
44 SecretKeyTrait,
45 SecretParams,
46 SignatureBytes,
47 Version,
48 },
49};
50use picky_asn1_x509::{
51 AlgorithmIdentifier,
52 DigestInfo,
53 ShaVariant,
54 signature::EcdsaSignatureValue,
55};
56use rand::prelude::{CryptoRng, Rng};
57
58use crate::{KeyMechanism, KeyType, NetHsm, PrivateKeyImport, key_type_matches_length};
59
60#[derive(Debug, thiserror::Error)]
61pub enum Error {
62 #[error("Decoding Base64 string failed: {0}")]
64 Base64Decode(#[from] base64ct::Error),
65
66 #[error("Elliptic curve error: {0}")]
68 EllipticCurve(#[from] p256::elliptic_curve::Error),
69
70 #[error("The OpenPGP User ID {user_id} is used more than once!")]
72 DuplicateUserId { user_id: OpenPgpUserId },
73
74 #[error("Invalid OpenPGP version: {0}")]
76 InvalidOpenPgpVersion(String),
77
78 #[error("Key data invalid: {0}")]
80 KeyData(String),
81
82 #[error("NetHSM error: {0}")]
84 NetHsm(String),
85
86 #[error("rPGP error: {0}")]
88 Pgp(#[from] pgp::errors::Error),
89
90 #[error("Transferable Secret Key is passphrase protected")]
92 PrivateKeyPassphraseProtected,
93
94 #[error("Unsupported multiple component keys")]
96 UnsupportedMultipleComponentKeys,
97
98 #[error("Unsupported key format: {public_params:?}")]
100 UnsupportedKeyFormat { public_params: Box<PublicParams> },
101
102 #[error("The OpenPGP User ID is too large: {user_id}")]
104 UserIdTooLarge { user_id: String },
105}
106
107#[derive(
109 Clone,
110 Copy,
111 Debug,
112 Default,
113 serde::Deserialize,
114 strum::Display,
115 strum::EnumIter,
116 Hash,
117 strum::IntoStaticStr,
118 Eq,
119 PartialEq,
120 serde::Serialize,
121)]
122#[serde(into = "String", try_from = "String")]
123pub enum OpenPgpVersion {
124 #[default]
128 #[strum(to_string = "4")]
129 V4,
130
131 #[strum(to_string = "6")]
135 V6,
136}
137
138impl AsRef<str> for OpenPgpVersion {
139 fn as_ref(&self) -> &str {
140 match self {
141 Self::V4 => "4",
142 Self::V6 => "6",
143 }
144 }
145}
146
147impl FromStr for OpenPgpVersion {
148 type Err = Error;
149
150 fn from_str(s: &str) -> Result<Self, Self::Err> {
178 match s {
179 "4" | "v4" | "V4" | "OpenPGPv4" => Ok(Self::V4),
180 "5" | "v5" | "V5" | "OpenPGPv5" => Err(Error::InvalidOpenPgpVersion(format!(
181 "{s} (\"we don't do these things around here\")"
182 ))),
183 "6" | "v6" | "V6" | "OpenPGPv6" => Ok(Self::V6),
184 _ => Err(Error::InvalidOpenPgpVersion(s.to_string())),
185 }
186 }
187}
188
189impl From<OpenPgpVersion> for String {
190 fn from(value: OpenPgpVersion) -> Self {
191 value.to_string()
192 }
193}
194
195impl TryFrom<String> for OpenPgpVersion {
196 type Error = Error;
197
198 fn try_from(value: String) -> Result<Self, Self::Error> {
199 Self::from_str(&value)
200 }
201}
202
203#[derive(Clone, Debug, Hash, Eq, PartialEq)]
205enum OpenPgpUserIdType {
206 Email(EmailAddress),
212
213 Plain(String),
217}
218
219#[derive(Clone, Debug, serde::Deserialize, Hash, Eq, PartialEq, serde::Serialize)]
232#[serde(into = "String", try_from = "String")]
233pub struct OpenPgpUserId(OpenPgpUserIdType);
234
235impl OpenPgpUserId {
236 pub fn new(user_id: String) -> Result<Self, Error> {
265 if user_id.len() > 4096 {
266 return Err(Error::UserIdTooLarge { user_id });
267 }
268 if let Ok(email) = EmailAddress::parse_with_options(
269 &user_id,
270 Options::default()
271 .with_required_tld()
272 .without_domain_literal(),
273 ) {
274 Ok(Self(OpenPgpUserIdType::Email(email)))
275 } else {
276 Ok(Self(OpenPgpUserIdType::Plain(user_id)))
277 }
278 }
279
280 pub fn is_email(&self) -> bool {
295 matches!(self.0, OpenPgpUserIdType::Email(..))
296 }
297}
298
299impl AsRef<str> for OpenPgpUserId {
300 fn as_ref(&self) -> &str {
301 match self.0.borrow() {
302 OpenPgpUserIdType::Email(user_id) => user_id.as_str(),
303 OpenPgpUserIdType::Plain(user_id) => user_id.as_str(),
304 }
305 }
306}
307
308impl Display for OpenPgpUserId {
309 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
310 write!(f, "{}", self.as_ref())
311 }
312}
313
314impl FromStr for OpenPgpUserId {
315 type Err = Error;
316
317 fn from_str(s: &str) -> Result<Self, Self::Err> {
318 Self::new(s.to_string())
319 }
320}
321
322impl From<OpenPgpUserId> for String {
323 fn from(value: OpenPgpUserId) -> Self {
324 value.to_string()
325 }
326}
327
328impl TryFrom<String> for OpenPgpUserId {
329 type Error = Error;
330
331 fn try_from(value: String) -> Result<Self, Self::Error> {
332 Self::new(value)
333 }
334}
335
336#[derive(Clone, Debug, serde::Deserialize, Hash, Eq, PartialEq, serde::Serialize)]
340#[serde(into = "Vec<String>", try_from = "Vec<String>")]
341pub struct OpenPgpUserIdList(Vec<OpenPgpUserId>);
342
343impl OpenPgpUserIdList {
344 pub fn new(user_ids: Vec<OpenPgpUserId>) -> Result<Self, Error> {
373 let mut set = HashSet::new();
374 for user_id in user_ids.iter() {
375 if !set.insert(user_id) {
376 return Err(Error::DuplicateUserId {
377 user_id: user_id.to_owned(),
378 });
379 }
380 }
381 Ok(Self(user_ids))
382 }
383
384 pub fn iter(&self) -> impl Iterator<Item = &OpenPgpUserId> {
386 self.0.iter()
387 }
388}
389
390impl AsRef<[OpenPgpUserId]> for OpenPgpUserIdList {
391 fn as_ref(&self) -> &[OpenPgpUserId] {
392 &self.0
393 }
394}
395
396impl From<OpenPgpUserIdList> for Vec<String> {
397 fn from(value: OpenPgpUserIdList) -> Self {
398 value
399 .iter()
400 .map(|user_id| user_id.to_string())
401 .collect::<Vec<String>>()
402 }
403}
404
405impl TryFrom<Vec<String>> for OpenPgpUserIdList {
406 type Error = Error;
407
408 fn try_from(value: Vec<String>) -> Result<Self, Self::Error> {
409 let user_ids = {
410 let mut user_ids: Vec<OpenPgpUserId> = vec![];
411 for user_id in value {
412 user_ids.push(OpenPgpUserId::new(user_id)?)
413 }
414 user_ids
415 };
416 OpenPgpUserIdList::new(user_ids)
417 }
418}
419
420struct HsmKey<'a, 'b> {
425 public_key: PublicKey,
426 nethsm: &'a NetHsm,
427 key_id: &'b crate::KeyId,
428}
429
430impl Debug for HsmKey<'_, '_> {
431 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
432 f.debug_struct("HsmKey")
433 .field("public_key", &self.public_key)
434 .field("key_id", &self.key_id)
435 .finish()
436 }
437}
438
439#[inline]
445fn to_rpgp_error(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> pgp::errors::Error {
446 pgp::errors::Error::IOError(std::io::Error::other(e))
447}
448
449fn parse_signature(sig_type: crate::SignatureType, sig: &[u8]) -> pgp::errors::Result<Vec<Mpi>> {
451 use crate::SignatureType::*;
452 Ok(match sig_type {
453 EcdsaP256 | EcdsaP384 | EcdsaP521 => {
454 let sig: EcdsaSignatureValue = picky_asn1_der::from_bytes(sig).map_err(|e| {
455 error!("DER decoding error when parsing ECDSA signature: {e:?}");
456 to_rpgp_error(e)
457 })?;
458 vec![
459 Mpi::from_slice(sig.r.as_unsigned_bytes_be()),
460 Mpi::from_slice(sig.s.as_unsigned_bytes_be()),
461 ]
462 }
463 EdDsa => {
464 if sig.len() != 64 {
465 return Err(pgp::errors::Error::InvalidKeyLength);
466 }
467
468 vec![Mpi::from_slice(&sig[..32]), Mpi::from_slice(&sig[32..])]
469 }
470 Pkcs1 => {
471 vec![Mpi::from_slice(sig)]
473 }
474 param => {
475 return Err(pgp::errors::Error::Unsupported(format!(
476 "Unsupoprted key type: {param:?}"
477 )));
478 }
479 })
480}
481
482impl<'a, 'b> HsmKey<'a, 'b> {
483 fn new(nethsm: &'a NetHsm, public_key: PublicKey, key_id: &'b crate::KeyId) -> Self {
485 Self {
486 nethsm,
487 public_key,
488 key_id,
489 }
490 }
491
492 fn sign_mode(&self) -> pgp::errors::Result<crate::SignatureType> {
494 Ok(match self.public_key.public_params() {
495 PublicParams::ECDSA(ecdsa) => match ecdsa {
496 EcdsaPublicParams::P256 { .. } => crate::SignatureType::EcdsaP256,
497 EcdsaPublicParams::P384 { .. } => crate::SignatureType::EcdsaP384,
498 EcdsaPublicParams::P521 { .. } => crate::SignatureType::EcdsaP521,
499 param => {
500 return Err(pgp::errors::Error::Unsupported(format!(
501 "Unsupported EC key type: {param:?}"
502 )));
503 }
504 },
505 PublicParams::EdDSALegacy { .. } => crate::SignatureType::EdDsa,
506 PublicParams::RSA { .. } => crate::SignatureType::Pkcs1,
507 param => {
508 return Err(pgp::errors::Error::Unsupported(format!(
509 "Unsupported key type: {param:?}"
510 )));
511 }
512 })
513 }
514}
515
516impl PublicKeyTrait for HsmKey<'_, '_> {
517 fn verify_signature(
518 &self,
519 hash: pgp::crypto::hash::HashAlgorithm,
520 data: &[u8],
521 sig: &SignatureBytes,
522 ) -> pgp::errors::Result<()> {
523 self.public_key.verify_signature(hash, data, sig)
524 }
525
526 fn encrypt<R: CryptoRng + Rng>(
527 &self,
528 rng: R,
529 plain: &[u8],
530 esk_type: EskType,
531 ) -> pgp::errors::Result<PkeskBytes> {
532 self.public_key.encrypt(rng, plain, esk_type)
533 }
534
535 fn serialize_for_hashing(&self, writer: &mut impl std::io::Write) -> pgp::errors::Result<()> {
536 self.public_key.serialize_for_hashing(writer)
537 }
538
539 fn version(&self) -> KeyVersion {
540 self.public_key.version()
541 }
542
543 fn fingerprint(&self) -> pgp::types::Fingerprint {
544 self.public_key.fingerprint()
545 }
546
547 fn key_id(&self) -> KeyId {
548 self.public_key.key_id()
549 }
550
551 fn algorithm(&self) -> PublicKeyAlgorithm {
552 self.public_key.algorithm()
553 }
554
555 fn created_at(&self) -> &chrono::DateTime<chrono::Utc> {
556 self.public_key.created_at()
557 }
558
559 fn expiration(&self) -> Option<u16> {
560 self.public_key.expiration()
561 }
562
563 fn public_params(&self) -> &PublicParams {
564 self.public_key.public_params()
565 }
566}
567
568fn prepare_digest_data(
578 signature_type: crate::SignatureType,
579 hash: HashAlgorithm,
580 digest: &[u8],
581) -> pgp::errors::Result<Cow<'_, [u8]>> {
582 Ok(match signature_type {
583 crate::SignatureType::Pkcs1 => picky_asn1_der::to_vec(&DigestInfo {
588 oid: hash_to_oid(hash)?,
589 digest: digest.to_vec().into(),
590 })
591 .map_err(|e| {
592 error!("Encoding signature to PKCS#1 format failed: {e:?}");
593 to_rpgp_error(e)
594 })?
595 .into(),
596
597 crate::SignatureType::EcdsaP224 => digest[..usize::min(28, digest.len())].into(),
600 crate::SignatureType::EcdsaP256 => digest[..usize::min(32, digest.len())].into(),
601 crate::SignatureType::EcdsaP384 => digest[..usize::min(48, digest.len())].into(),
602
603 _ => digest.into(),
606 })
607}
608
609impl SecretKeyTrait for HsmKey<'_, '_> {
610 type PublicKey = PublicKey;
611
612 type Unlocked = Self;
613
614 fn unlock<F, G, T>(&self, _pw: F, work: G) -> pgp::errors::Result<T>
615 where
616 F: FnOnce() -> String,
617 G: FnOnce(&Self::Unlocked) -> pgp::errors::Result<T>,
618 {
619 work(self)
620 }
621
622 fn create_signature<F>(
623 &self,
624 _key_pw: F,
625 hash: HashAlgorithm,
626 data: &[u8],
627 ) -> pgp::errors::Result<SignatureBytes>
628 where
629 F: FnOnce() -> String,
630 {
631 let signature_type = self.sign_mode()?;
632 let request_data = prepare_digest_data(signature_type, hash, data)?;
633
634 let sig = self
635 .nethsm
636 .sign_digest(self.key_id, signature_type, &request_data)
637 .map_err(|e| {
638 error!("NetHsm::sign_digest failed: {e:?}");
639 to_rpgp_error(e)
640 })?;
641
642 Ok(parse_signature(signature_type, &sig)?.into())
643 }
644
645 fn public_key(&self) -> Self::PublicKey {
646 self.public_key.clone()
647 }
648
649 fn hash_alg(&self) -> HashAlgorithm {
650 HashAlgorithm::SHA2_512
651 }
652}
653
654pub fn add_certificate(
656 nethsm: &NetHsm,
657 flags: KeyUsageFlags,
658 key_id: &crate::KeyId,
659 user_id: OpenPgpUserId,
660 created_at: DateTime<Utc>,
661 version: OpenPgpVersion,
662) -> Result<Vec<u8>, crate::Error> {
663 if version != OpenPgpVersion::V4 {
664 unimplemented!(
665 "Support for creating OpenPGP {version} certificates is not yet implemented!"
666 );
667 }
668
669 let public_key = nethsm.get_key(key_id)?;
670 let signer = HsmKey::new(nethsm, hsm_pk_to_pgp_pk(public_key, created_at)?, key_id);
671 let mut keyflags: KeyFlags = flags.into();
672 keyflags.set_certify(true);
674
675 let composed_pk = pgp::PublicKey::new(
676 signer.public_key(),
677 KeyDetails::new(
678 UserId::from_str(Default::default(), user_id.as_ref()),
679 vec![],
680 vec![],
681 keyflags,
682 Default::default(),
683 Default::default(),
684 vec![CompressionAlgorithm::Uncompressed].into(),
685 vec![].into(),
686 None,
687 ),
688 vec![],
689 );
690 let signed_pk = composed_pk
691 .sign(rand::thread_rng(), &signer, String::new)
692 .map_err(Error::Pgp)?;
693 let mut buffer = vec![];
694 signed_pk.to_writer(&mut buffer).map_err(Error::Pgp)?;
695 Ok(buffer)
696}
697
698fn hash_to_oid(hash: HashAlgorithm) -> pgp::errors::Result<AlgorithmIdentifier> {
700 Ok(AlgorithmIdentifier::new_sha(match hash {
701 HashAlgorithm::SHA1 => ShaVariant::SHA1,
702 HashAlgorithm::SHA2_256 => ShaVariant::SHA2_256,
703 HashAlgorithm::SHA2_384 => ShaVariant::SHA2_384,
704 HashAlgorithm::SHA2_512 => ShaVariant::SHA2_512,
705 HashAlgorithm::SHA2_224 => ShaVariant::SHA2_224,
706 HashAlgorithm::SHA3_256 => ShaVariant::SHA3_256,
707 HashAlgorithm::SHA3_512 => ShaVariant::SHA3_512,
708 hash => {
709 return Err(pgp::errors::Error::Unsupported(format!(
710 "Unsupported hash: {hash:?}"
711 )));
712 }
713 }))
714}
715
716pub fn tsk_to_private_key_import(
726 key_data: &[u8],
727) -> Result<(PrivateKeyImport, KeyMechanism), crate::Error> {
728 let key = SignedSecretKey::from_bytes(key_data).map_err(Error::Pgp)?;
729 if !key.secret_subkeys.is_empty() {
730 return Err(crate::Error::OpenPgp(
731 Error::UnsupportedMultipleComponentKeys,
732 ));
733 }
734 let SecretParams::Plain(secret) = key.primary_key.secret_params() else {
735 return Err(crate::Error::OpenPgp(Error::PrivateKeyPassphraseProtected));
736 };
737 Ok(match (secret, key.public_params()) {
738 (PlainSecretParams::RSA { p, q, .. }, PublicParams::RSA { n, e }) => {
739 key_type_matches_length(KeyType::Rsa, Some(n.as_bytes().len() as u32 * 8))?;
741
742 (
743 PrivateKeyImport::from_rsa(
744 p.as_bytes().to_vec(),
745 q.as_bytes().to_vec(),
746 e.as_bytes().to_vec(),
747 ),
748 KeyMechanism::RsaSignaturePkcs1,
749 )
750 }
751 (PlainSecretParams::ECDSA(bytes), _) => {
752 let ec = if let PublicParams::ECDSA(pp) = key.primary_key.public_params() {
753 match pp {
754 EcdsaPublicParams::P256 { .. } => crate::KeyType::EcP256,
755 EcdsaPublicParams::P384 { .. } => crate::KeyType::EcP384,
756 EcdsaPublicParams::P521 { .. } => crate::KeyType::EcP521,
757 _ => {
758 return Err(crate::Error::OpenPgp(Error::UnsupportedKeyFormat {
759 public_params: Box::new(key.public_params().clone()),
760 }));
761 }
762 }
763 } else {
764 return Err(crate::Error::OpenPgp(Error::UnsupportedKeyFormat {
765 public_params: Box::new(key.public_params().clone()),
766 }));
767 };
768
769 (
770 PrivateKeyImport::from_raw_bytes(ec, bytes)?,
771 KeyMechanism::EcdsaSignature,
772 )
773 }
774 (PlainSecretParams::EdDSALegacy(bytes), _) => (
775 PrivateKeyImport::from_raw_bytes(crate::KeyType::Curve25519, bytes)?,
776 KeyMechanism::EdDsaSignature,
777 ),
778 (_, public_params) => {
779 return Err(crate::Error::OpenPgp(Error::UnsupportedKeyFormat {
780 public_params: Box::new(public_params.clone()),
781 }));
782 }
783 })
784}
785
786pub fn sign(
788 nethsm: &NetHsm,
789 key_id: &crate::KeyId,
790 message: &[u8],
791) -> Result<Vec<u8>, crate::Error> {
792 let public_key = nethsm.get_key_certificate(key_id)?;
793
794 let signer = HsmKey::new(
795 nethsm,
796 SignedPublicKey::from_bytes(&*public_key)
797 .map_err(Error::Pgp)?
798 .primary_key,
799 key_id,
800 );
801
802 let mut sig_config =
803 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
804 sig_config.hashed_subpackets = vec![
805 Subpacket::regular(SubpacketData::SignatureCreationTime(
806 std::time::SystemTime::now().into(),
807 )),
808 Subpacket::regular(SubpacketData::Issuer(signer.key_id())),
809 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint())),
810 ];
811
812 let mut hasher = sig_config.hash_alg.new_hasher().map_err(Error::Pgp)?;
813 sig_config
814 .hash_data_to_sign(&mut *hasher, message)
815 .map_err(Error::Pgp)?;
816
817 let len = sig_config
818 .hash_signature_data(&mut hasher)
819 .map_err(Error::Pgp)?;
820
821 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
822
823 let hash = &hasher.finish()[..];
824
825 let signed_hash_value = [hash[0], hash[1]];
826 let raw_sig = signer
827 .create_signature(String::new, sig_config.hash_alg, hash)
828 .map_err(Error::Pgp)?;
829
830 let signature = pgp::Signature::from_config(sig_config, signed_hash_value, raw_sig);
831
832 let mut out = vec![];
833 pgp::packet::write_packet(&mut out, &signature).map_err(Error::Pgp)?;
834
835 Ok(out)
836}
837
838pub fn sign_hasher_state(
873 nethsm: &NetHsm,
874 key_id: &crate::KeyId,
875 state: impl sha2::Digest + Clone + std::io::Write,
876) -> Result<String, crate::Error> {
877 let public_key = nethsm.get_key_certificate(key_id)?;
878
879 let signer = HsmKey::new(
880 nethsm,
881 SignedPublicKey::from_bytes(public_key.as_slice())
882 .map_err(Error::Pgp)?
883 .primary_key,
884 key_id,
885 );
886
887 let hasher = state.clone();
888 let file_hash = hasher.finalize();
889
890 let sig_config = {
891 let mut sig_config =
892 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
893 sig_config.hashed_subpackets = vec![
894 Subpacket::regular(SubpacketData::SignatureCreationTime(
895 std::time::SystemTime::now().into(),
896 )),
897 Subpacket::regular(SubpacketData::Issuer(signer.key_id())),
898 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint())),
899 Subpacket::regular(SubpacketData::Notation(Notation {
900 readable: false,
901 name: "data-digest@archlinux.org".into(),
902 value: file_hash[..].into(),
903 })),
904 ];
905 sig_config
906 };
907
908 let hasher = {
909 let mut hasher = state.clone();
910 let write: &mut dyn std::io::Write = &mut hasher;
911
912 let len = sig_config.hash_signature_data(write).map_err(Error::Pgp)?;
913
914 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
915 hasher
916 };
917
918 let hash = &hasher.finalize()[..];
919
920 let signed_hash_value = [hash[0], hash[1]];
921
922 let raw_sig = signer
923 .create_signature(String::new, sig_config.hash_alg, hash)
924 .map_err(Error::Pgp)?;
925
926 let signature = pgp::Signature::from_config(sig_config, signed_hash_value, raw_sig);
927
928 let signature = StandaloneSignature { signature };
929 Ok(signature
930 .to_armored_string(ArmorOptions::default())
931 .map_err(Error::Pgp)?)
932}
933
934fn hsm_pk_to_pgp_pk(
940 pk: nethsm_sdk_rs::models::PublicKey,
941 created_at: DateTime<Utc>,
942) -> Result<PublicKey, Error> {
943 let public = pk
944 .public
945 .ok_or(Error::KeyData("missing public key data".into()))?;
946 let key_type: KeyType = pk.r#type.into();
947 Ok(match key_type {
948 KeyType::Rsa => PublicKey::new(
949 Version::New,
950 KeyVersion::V4,
951 PublicKeyAlgorithm::RSA,
952 created_at,
953 None,
954 PublicParams::RSA {
955 n: Mpi::from_raw(Base64::decode_vec(
956 &public
957 .modulus
958 .ok_or(Error::KeyData("missing RSA modulus".into()))?,
959 )?),
960 e: Mpi::from_raw(Base64::decode_vec(
961 &public
962 .public_exponent
963 .ok_or(Error::KeyData("missing RSA exponent".into()))?,
964 )?),
965 },
966 )?,
967 KeyType::Curve25519 => {
968 let pubkey = Base64::decode_vec(
969 &public
970 .data
971 .ok_or(Error::KeyData("missing ed25519 public key data".into()))?,
972 )?;
973 let mut bytes = vec![0x40];
974 bytes.extend(pubkey);
975
976 PublicKey::new(
977 Version::New,
978 KeyVersion::V4,
979 PublicKeyAlgorithm::EdDSALegacy,
980 created_at,
981 None,
982 PublicParams::EdDSALegacy {
983 curve: ECCCurve::Ed25519,
984 q: Mpi::from_raw(bytes),
985 },
986 )?
987 }
988 curve @ (KeyType::EcP256 | KeyType::EcP384 | KeyType::EcP521) => {
989 let pubkey = Base64::decode_vec(
990 &public
991 .data
992 .ok_or(Error::KeyData("missing EC public key data".into()))?,
993 )?;
994 let key = match curve {
995 KeyType::EcP256 => EcdsaPublicParams::P256 {
996 key: p256::PublicKey::from_sec1_bytes(&pubkey)?,
997 p: Mpi::from_raw(pubkey),
998 },
999 KeyType::EcP384 => EcdsaPublicParams::P384 {
1000 key: p384::PublicKey::from_sec1_bytes(&pubkey)?,
1001 p: Mpi::from_raw(pubkey),
1002 },
1003 KeyType::EcP521 => EcdsaPublicParams::P521 {
1004 key: p521::PublicKey::from_sec1_bytes(&pubkey)?,
1005 p: Mpi::from_raw(pubkey),
1006 },
1007 _ => unreachable!(),
1008 };
1009
1010 PublicKey::new(
1011 Version::New,
1012 KeyVersion::V4,
1013 PublicKeyAlgorithm::ECDSA,
1014 created_at,
1015 None,
1016 PublicParams::ECDSA(key),
1017 )?
1018 }
1019
1020 _ => {
1021 return Err(pgp::errors::Error::Unsupported(
1022 "unsupported key type".into(),
1023 ))?;
1024 }
1025 })
1026}
1027
1028pub fn extract_certificate(key_data: &[u8]) -> Result<Vec<u8>, crate::Error> {
1030 let key = SignedSecretKey::from_bytes(key_data).map_err(Error::Pgp)?;
1031 let public: SignedPublicKey = key.into();
1032 let mut buffer = vec![];
1033 public.to_writer(&mut buffer).map_err(Error::Pgp)?;
1034 Ok(buffer)
1035}
1036
1037#[derive(Debug, Default)]
1039pub struct KeyUsageFlags(KeyFlags);
1040
1041impl KeyUsageFlags {
1042 pub fn set_sign(&mut self) {
1044 self.0.set_sign(true);
1045 }
1046
1047 pub fn clear_sign(&mut self) {
1049 self.0.set_sign(false);
1050 }
1051}
1052
1053impl From<KeyUsageFlags> for KeyFlags {
1054 fn from(value: KeyUsageFlags) -> Self {
1055 value.0
1056 }
1057}
1058
1059#[cfg(test)]
1060mod tests {
1061 use nethsm_sdk_rs::models::{KeyMechanism, KeyPublicData, KeyRestrictions, KeyType};
1062 use pgp::{
1063 crypto::ecc_curve::ECCCurve,
1064 types::{EcdsaPublicParams, PublicParams},
1065 };
1066 use rstest::rstest;
1067 use testresult::TestResult;
1068
1069 use super::*;
1070
1071 #[test]
1072 fn convert_ed25519_to_pgp() -> TestResult {
1073 let hsm_key = nethsm_sdk_rs::models::PublicKey {
1074 mechanisms: vec![KeyMechanism::EdDsaSignature],
1075 r#type: KeyType::Curve25519,
1076 restrictions: Box::new(KeyRestrictions {
1077 tags: Some(vec!["signing1".into()]),
1078 }),
1079 public: Some(Box::new(KeyPublicData {
1080 modulus: None,
1081 public_exponent: None,
1082 data: Some("/ODoaDzX9xDjpx2LfR0DCIgdxqOndY9tukEFLVCObQo=".into()),
1083 })),
1084 operations: 1,
1085 };
1086
1087 let pgp_key = hsm_pk_to_pgp_pk(hsm_key, DateTime::UNIX_EPOCH)?;
1088 let PublicParams::EdDSALegacy { curve, q } = pgp_key.public_params() else {
1089 panic!("Wrong type of public params");
1090 };
1091 assert_eq!(curve, &ECCCurve::Ed25519);
1092 assert_eq!(
1093 q.to_vec(),
1094 [
1095 64, 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136,
1096 29, 198, 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10
1097 ]
1098 );
1099
1100 Ok(())
1101 }
1102
1103 #[test]
1104 fn convert_p256_to_pgp() -> TestResult {
1105 let hsm_key = nethsm_sdk_rs::models::PublicKey {
1106 mechanisms: vec![KeyMechanism::EcdsaSignature],
1107 r#type: KeyType::EcP256,
1108 restrictions: Box::new(KeyRestrictions {
1109 tags: Some(vec!["signing2".into()]),
1110 }),
1111 public: Some(Box::new(KeyPublicData {
1112 modulus: None,
1113 public_exponent: None,
1114 data: Some(
1115 "BN5q7GCR8w1RtXdMBR1IcIaCqbbn92vM5LItTcRbdXo5RfDwhnKK6D8tjWakqXbWY9eKelkCtALtD/hoU44WuYU="
1116 .into(),
1117 ),
1118 })),
1119 operations: 1,
1120 };
1121 let pgp_key = hsm_pk_to_pgp_pk(hsm_key, DateTime::UNIX_EPOCH)?;
1122 let PublicParams::ECDSA(EcdsaPublicParams::P256 { p, .. }) = pgp_key.public_params() else {
1123 panic!("Wrong type of public params");
1124 };
1125 assert_eq!(
1126 p.to_vec(),
1127 [
1128 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130,
1129 169, 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240,
1130 240, 134, 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122,
1131 89, 2, 180, 2, 237, 15, 248, 104, 83, 142, 22, 185, 133
1132 ]
1133 );
1134
1135 Ok(())
1136 }
1137
1138 #[test]
1139 fn convert_p384_to_pgp() -> TestResult {
1140 let hsm_key = nethsm_sdk_rs::models::PublicKey {
1141 mechanisms: vec![KeyMechanism::EcdsaSignature],
1142 r#type: KeyType::EcP384,
1143 restrictions: Box::new(KeyRestrictions {
1144 tags: Some(vec!["signing2".into()]),
1145 }),
1146 public: Some(Box::new(KeyPublicData {
1147 modulus: None,
1148 public_exponent: None,
1149 data: Some(
1150 "BH+Ik2+7v4NUpnZDTGs0jq9I+kDFTJqiMNOHP5k81agoKW8ICEJ13aL06dLNzkZAdB5iulgRCEuX/Htitii3BhxuHTUPWuN0uVKGhgYRddpTteaaauv0cOPni9la3O+/lA=="
1151 .into(),
1152 ),
1153 })),
1154 operations: 3,
1155 };
1156 let pgp_key = hsm_pk_to_pgp_pk(hsm_key, DateTime::UNIX_EPOCH)?;
1157 let PublicParams::ECDSA(EcdsaPublicParams::P384 { p, .. }) = pgp_key.public_params() else {
1158 panic!("Wrong type of public params");
1159 };
1160 assert_eq!(
1161 p.to_vec(),
1162 [
1163 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72,
1164 250, 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8,
1165 66, 117, 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8,
1166 75, 151, 252, 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82,
1167 134, 134, 6, 17, 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139,
1168 217, 90, 220, 239, 191, 148
1169 ]
1170 );
1171
1172 Ok(())
1173 }
1174
1175 #[test]
1176 fn convert_p521_to_pgp() -> TestResult {
1177 let hsm_key = nethsm_sdk_rs::models::PublicKey {
1178 mechanisms: vec![KeyMechanism::EcdsaSignature],
1179 r#type: KeyType::EcP521,
1180 restrictions: Box::new(KeyRestrictions {
1181 tags: Some(vec!["signing2".into()]),
1182 }),
1183 public: Some(Box::new(KeyPublicData {
1184 modulus: None,
1185 public_exponent: None,
1186 data: Some(
1187 "BAEhJ8HuyTN/DBjAoXD3H7jTdl+TwOwJ3taKwq2q+HsBislgZjeg1JZlOus1Mh4viKv0iuwaviid0D9cqsO2UHLN/QHTWGbzQw6fLiNZvCaGuNDf1c5+aiFMxvAgbDB8qp4eBAsl6f6ro5kKQXbpT7NauRVHYxUv32TgxG5mcRpnf+ovUQ=="
1188 .into(),
1189 ),
1190 })),
1191 operations: 2,
1192 };
1193 let pgp_key = hsm_pk_to_pgp_pk(hsm_key, DateTime::UNIX_EPOCH)?;
1194 let PublicParams::ECDSA(EcdsaPublicParams::P521 { p, .. }) = pgp_key.public_params() else {
1195 panic!("Wrong type of public params");
1196 };
1197 assert_eq!(
1198 p.to_vec(),
1199 [
1200 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211,
1201 118, 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96,
1202 102, 55, 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26,
1203 190, 40, 157, 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243,
1204 67, 14, 159, 46, 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76,
1205 198, 240, 32, 108, 48, 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10,
1206 65, 118, 233, 79, 179, 90, 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102,
1207 113, 26, 103, 127, 234, 47, 81
1208 ]
1209 );
1210
1211 Ok(())
1212 }
1213
1214 #[test]
1215 fn convert_rsa_to_pgp() -> TestResult {
1216 let hsm_key = nethsm_sdk_rs::models::PublicKey {
1217 mechanisms: vec![KeyMechanism::RsaSignaturePkcs1],
1218 r#type: KeyType::Rsa,
1219 restrictions: Box::new(KeyRestrictions {
1220 tags: Some(vec!["signing8".into()]) }),
1221 public: Some(Box::new(KeyPublicData {
1222 modulus: Some("4386l1aC1e4N93rxM+Npj+dy0CGY0W3PNbOTBGRj7tTEflkEl2qx2xW7kyme8sLQQ/yxhyJ4mqo/ggR9ODfvYytzxsS/n/MNZwdATGC4QDBjPv74s/51nC/gZHq9VzvYq3bmF0e0WNiXRT3p53Zofmv1CBDPBEDrrJq3Mq+O3+TH8/ur3OOMgvNx2CDgwwQ1WGSW3XITN9ekZpoj/h8cwxFkz5ljmygCLRtXdNWrzVJGW3G5L/Jz9sdSfE2tyb8+312IVFJ57zcvRygqAkkS11uYIPxuoabT6IJ8SpScfqltGsU3jiALKyFRV58I91KUlXegjUVR31ExFc0eADuhuw==".into()),
1223 public_exponent: Some("AQAB".into()),
1224 data: None })),
1225 operations: 2 };
1226 let pgp_key = hsm_pk_to_pgp_pk(hsm_key, DateTime::UNIX_EPOCH)?;
1227 let PublicParams::RSA { e, n } = pgp_key.public_params() else {
1228 panic!("Wrong type of public params");
1229 };
1230 assert_eq!(e.to_vec(), [1, 0, 1]);
1231 assert_eq!(
1232 n.to_vec(),
1233 [
1234 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
1235 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
1236 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
1237 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
1238 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
1239 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
1240 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
1241 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
1242 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
1243 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
1244 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
1245 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
1246 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
1247 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
1248 59, 161, 187
1249 ]
1250 );
1251
1252 Ok(())
1253 }
1254
1255 #[test]
1256 fn parse_rsa_signature_produces_valid_data() -> TestResult {
1257 let sig = parse_signature(crate::SignatureType::Pkcs1, &[0, 1, 2])?;
1258 assert_eq!(sig.len(), 1);
1259 assert_eq!(&sig[0][..], &[1, 2]);
1260
1261 Ok(())
1262 }
1263
1264 #[test]
1265 fn parse_ed25519_signature_produces_valid_data() -> TestResult {
1266 let sig = parse_signature(
1267 crate::SignatureType::EdDsa,
1268 &[
1269 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1270 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1271 1, 1, 1, 1, 1, 1, 1, 1,
1272 ],
1273 )?;
1274 assert_eq!(sig.len(), 2);
1275 assert_eq!(sig[0].as_bytes(), vec![2; 32]);
1276 assert_eq!(sig[1].as_bytes(), vec![1; 32]);
1277
1278 Ok(())
1279 }
1280
1281 #[test]
1282 fn parse_p256_signature_produces_valid_data() -> TestResult {
1283 let sig = parse_signature(
1284 crate::SignatureType::EcdsaP256,
1285 &[
1286 48, 70, 2, 33, 0, 193, 176, 219, 0, 133, 254, 212, 239, 236, 122, 85, 239, 73, 161,
1287 179, 53, 100, 172, 103, 45, 123, 21, 169, 28, 59, 150, 72, 92, 242, 9, 53, 143, 2,
1288 33, 0, 165, 1, 144, 97, 102, 109, 66, 50, 185, 234, 211, 150, 253, 228, 210, 126,
1289 26, 0, 189, 184, 230, 163, 36, 203, 232, 161, 12, 75, 121, 171, 45, 107,
1290 ],
1291 )?;
1292 assert_eq!(sig.len(), 2);
1293 assert_eq!(
1294 sig[0].as_bytes(),
1295 [
1296 193, 176, 219, 0, 133, 254, 212, 239, 236, 122, 85, 239, 73, 161, 179, 53, 100,
1297 172, 103, 45, 123, 21, 169, 28, 59, 150, 72, 92, 242, 9, 53, 143
1298 ]
1299 );
1300 assert_eq!(
1301 sig[1].as_bytes(),
1302 [
1303 165, 1, 144, 97, 102, 109, 66, 50, 185, 234, 211, 150, 253, 228, 210, 126, 26, 0,
1304 189, 184, 230, 163, 36, 203, 232, 161, 12, 75, 121, 171, 45, 107
1305 ]
1306 );
1307
1308 Ok(())
1309 }
1310
1311 #[test]
1312 fn parse_p384_signature_produces_valid_data() -> TestResult {
1313 let sig = parse_signature(
1314 crate::SignatureType::EcdsaP384,
1315 &[
1316 48, 101, 2, 49, 0, 134, 13, 108, 74, 135, 234, 174, 105, 208, 46, 109, 18, 77, 21,
1317 177, 59, 73, 150, 228, 26, 244, 134, 187, 217, 172, 34, 2, 1, 229, 123, 105, 202,
1318 132, 233, 72, 41, 243, 138, 127, 107, 135, 95, 139, 19, 121, 179, 170, 27, 2, 48,
1319 44, 80, 117, 90, 18, 137, 36, 190, 8, 60, 201, 235, 242, 168, 164, 245, 119, 136,
1320 207, 178, 237, 64, 117, 69, 218, 189, 209, 110, 2, 9, 191, 194, 70, 50, 227, 47, 6,
1321 34, 8, 135, 43, 188, 236, 192, 184, 227, 59, 40,
1322 ],
1323 )?;
1324 assert_eq!(sig.len(), 2);
1325 assert_eq!(
1326 sig[0].as_bytes(),
1327 [
1328 134, 13, 108, 74, 135, 234, 174, 105, 208, 46, 109, 18, 77, 21, 177, 59, 73, 150,
1329 228, 26, 244, 134, 187, 217, 172, 34, 2, 1, 229, 123, 105, 202, 132, 233, 72, 41,
1330 243, 138, 127, 107, 135, 95, 139, 19, 121, 179, 170, 27
1331 ]
1332 );
1333 assert_eq!(
1334 sig[1].as_bytes(),
1335 [
1336 44, 80, 117, 90, 18, 137, 36, 190, 8, 60, 201, 235, 242, 168, 164, 245, 119, 136,
1337 207, 178, 237, 64, 117, 69, 218, 189, 209, 110, 2, 9, 191, 194, 70, 50, 227, 47, 6,
1338 34, 8, 135, 43, 188, 236, 192, 184, 227, 59, 40
1339 ]
1340 );
1341
1342 Ok(())
1343 }
1344
1345 #[test]
1346 fn parse_p521_signature_produces_valid_data() -> TestResult {
1347 let sig = parse_signature(
1348 crate::SignatureType::EcdsaP521,
1349 &[
1350 48, 129, 136, 2, 66, 0, 203, 246, 21, 57, 217, 6, 101, 73, 103, 113, 98, 39, 223,
1351 246, 199, 136, 238, 213, 134, 163, 153, 151, 116, 237, 207, 181, 107, 183, 204,
1352 110, 97, 160, 95, 160, 193, 3, 219, 46, 105, 191, 0, 139, 124, 234, 90, 125, 114,
1353 115, 205, 109, 15, 193, 166, 100, 224, 108, 87, 143, 240, 65, 41, 93, 164, 166, 2,
1354 2, 66, 1, 203, 115, 121, 219, 49, 18, 3, 101, 130, 153, 95, 80, 27, 148, 249, 221,
1355 198, 251, 149, 118, 119, 32, 44, 160, 24, 125, 72, 161, 168, 71, 48, 138, 223, 200,
1356 37, 124, 234, 17, 237, 246, 13, 123, 102, 151, 83, 95, 186, 161, 112, 41, 158, 138,
1357 144, 55, 23, 110, 100, 185, 237, 13, 174, 83, 4, 153, 34,
1358 ],
1359 )?;
1360 assert_eq!(sig.len(), 2);
1361 assert_eq!(
1362 sig[0].as_bytes(),
1363 [
1364 203, 246, 21, 57, 217, 6, 101, 73, 103, 113, 98, 39, 223, 246, 199, 136, 238, 213,
1365 134, 163, 153, 151, 116, 237, 207, 181, 107, 183, 204, 110, 97, 160, 95, 160, 193,
1366 3, 219, 46, 105, 191, 0, 139, 124, 234, 90, 125, 114, 115, 205, 109, 15, 193, 166,
1367 100, 224, 108, 87, 143, 240, 65, 41, 93, 164, 166, 2
1368 ]
1369 );
1370 assert_eq!(
1371 sig[1].as_bytes(),
1372 [
1373 1, 203, 115, 121, 219, 49, 18, 3, 101, 130, 153, 95, 80, 27, 148, 249, 221, 198,
1374 251, 149, 118, 119, 32, 44, 160, 24, 125, 72, 161, 168, 71, 48, 138, 223, 200, 37,
1375 124, 234, 17, 237, 246, 13, 123, 102, 151, 83, 95, 186, 161, 112, 41, 158, 138,
1376 144, 55, 23, 110, 100, 185, 237, 13, 174, 83, 4, 153, 34
1377 ]
1378 );
1379
1380 Ok(())
1381 }
1382
1383 #[test]
1384 fn private_key_import_ed25199_is_correctly_zero_padded() -> TestResult {
1385 let mut key_data = vec![];
1386 SignedSecretKey::from_armor_single(std::fs::File::open(
1387 "tests/fixtures/ed25519-key-with-31-byte-private-key-scalar.asc",
1388 )?)?
1389 .0
1390 .to_writer(&mut key_data)?;
1391
1392 let import: nethsm_sdk_rs::models::KeyPrivateData =
1393 tsk_to_private_key_import(&key_data)?.0.into();
1394
1395 let data = Base64::decode_vec(&import.data.unwrap())?;
1396
1397 assert_eq!(data.len(), 32);
1400 assert_eq!(data[0], 0x00);
1401
1402 Ok(())
1403 }
1404
1405 #[test]
1406 fn private_key_import_rsa_key_with_nonstandard_moduli_is_read_correctly() -> TestResult {
1407 let mut key_data = vec![];
1408 SignedSecretKey::from_armor_single(std::fs::File::open(
1409 "tests/fixtures/rsa-key-with-modulus-e-257.asc",
1410 )?)?
1411 .0
1412 .to_writer(&mut key_data)?;
1413
1414 let import: nethsm_sdk_rs::models::KeyPrivateData =
1415 tsk_to_private_key_import(&key_data)?.0.into();
1416
1417 let data = Base64::decode_vec(&import.public_exponent.unwrap())?;
1418
1419 assert_eq!(data, vec![0x01, 0x01]); Ok(())
1423 }
1424
1425 #[test]
1426 fn rsa_digest_info_is_wrapped() -> TestResult {
1427 let data = prepare_digest_data(crate::SignatureType::Pkcs1, HashAlgorithm::SHA1, &[0; 20])?;
1428
1429 assert_eq!(
1430 data,
1431 vec![
1432 48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1433 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1434 ]
1435 );
1436
1437 Ok(())
1438 }
1439
1440 #[rstest]
1441 #[case(crate::SignatureType::EcdsaP224, 28)]
1442 #[case(crate::SignatureType::EcdsaP256, 32)]
1443 #[case(crate::SignatureType::EcdsaP384, 48)]
1444 #[case(crate::SignatureType::EcdsaP521, 64)]
1445 fn ecdsa_wrapped_up_to_max_len(
1446 #[case] sig_type: crate::SignatureType,
1447 #[case] max_len: usize,
1448 #[values(HashAlgorithm::SHA1, HashAlgorithm::SHA2_256, HashAlgorithm::SHA2_512)] hash_algo: HashAlgorithm,
1449 ) -> TestResult {
1450 let digest = hash_algo.new_hasher()?.finish();
1452 let data = prepare_digest_data(sig_type, hash_algo, &digest)?;
1453
1454 assert_eq!(
1458 data.len(),
1459 usize::min(max_len, digest.len()),
1460 "the data to be signed's length ({}) cannot exceed maximum length imposed by the curve ({})",
1461 data.len(),
1462 max_len
1463 );
1464
1465 Ok(())
1466 }
1467
1468 #[rstest]
1469 fn eddsa_is_not_wrapped(
1470 #[values(HashAlgorithm::SHA1, HashAlgorithm::SHA2_256, HashAlgorithm::SHA2_512)] hash_algo: HashAlgorithm,
1471 ) -> TestResult {
1472 let digest = hash_algo.new_hasher()?.finish();
1474
1475 let data = prepare_digest_data(crate::SignatureType::EdDsa, hash_algo, &digest)?;
1476
1477 assert_eq!(data, digest);
1478
1479 Ok(())
1480 }
1481}