1use std::{backtrace::Backtrace, io::Cursor};
4
5use digest_0_10_for_rpgp::{DynDigest, InvalidBufferSize};
6use ed25519_dalek_2_for_rpgp::VerifyingKey;
7use log::{error, warn};
8use p256_0_13_for_rpgp::PublicKey as P256PublicKey;
9use p384_0_13_for_rpgp::PublicKey as P384PublicKey;
10use p521_0_13_for_rpgp::PublicKey as P521PublicKey;
11use pgp::composed::SignedKeyDetails;
12pub use pgp::composed::{Deserializable, SignedSecretKey};
14pub use pgp::types::Timestamp;
15use pgp::{
16 composed::{ArmorOptions, DetachedSignature, SignedPublicKey},
17 crypto::{
18 ecdsa::SecretKey,
19 eddsa_legacy::SecretKey as EdDsaLegacySecretKey,
20 hash::HashAlgorithm,
21 public_key::PublicKeyAlgorithm,
22 },
23 packet::{
24 Notation as PgpNotation,
25 PacketTrait,
26 PubKeyInner,
27 PublicKey,
28 Signature,
29 SignatureConfig,
30 SignatureType,
31 Subpacket,
32 SubpacketData,
33 UserId,
34 },
35 ser::Serialize,
36 types::{
37 EcdsaPublicParams,
38 EddsaLegacyPublicParams,
39 Fingerprint,
40 KeyDetails,
41 KeyId,
42 KeyVersion,
43 Mpi,
44 Password,
45 PlainSecretParams,
46 PublicParams,
47 RsaPublicParams,
48 SecretParams,
49 SignatureBytes,
50 SigningKey as RpgpSigningKey,
51 },
52};
53use rand_0_8_for_rpgp::thread_rng;
54use rsa_0_9_for_rpgp::{BigUint, RsaPublicKey, traits::PublicKeyParts as _};
55use sha2::digest::Digest as _;
56
57use crate::{
58 key::{KeyMechanism, KeyType, PrivateKeyImport, key_type_matches_length},
59 openpgp::{OpenPgpKeyUsageFlags, OpenPgpUserId, OpenPgpVersion},
60 signer::{
61 error::Error,
62 traits::{RawPublicKey, RawSigningKey},
63 },
64};
65
66#[derive(Debug)]
73pub struct Notation<'name, 'value> {
74 pub name: &'name str,
76
77 pub value: &'value str,
79}
80
81pub(crate) struct SigningKey<'a> {
86 public_key: PublicKey,
87 raw_signer: &'a dyn RawSigningKey,
88 user_id: UserId,
89}
90
91impl std::fmt::Debug for SigningKey<'_> {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 f.debug_struct("SigningKey")
94 .field("public_key", &self.public_key)
95 .finish()
96 }
97}
98
99#[derive(Debug)]
110pub struct EmptyEd25519Signer;
111
112impl RawSigningKey for EmptyEd25519Signer {
113 fn key_id(&self) -> String {
115 "unused".into()
116 }
117
118 fn sign(&self, _digest: &[u8]) -> Result<Vec<Vec<u8>>, crate::Error> {
124 Ok(vec![vec![0; 32], vec![0; 32]])
125 }
126
127 fn certificate(&self) -> Result<Option<Vec<u8>>, crate::Error> {
133 Ok(None)
134 }
135
136 fn public(&self) -> Result<RawPublicKey, crate::Error> {
142 Ok(RawPublicKey::Ed25519(vec![0; 32]))
143 }
144}
145
146#[inline]
152fn to_rpgp_error(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> pgp::errors::Error {
153 pgp::errors::Error::IO {
154 source: std::io::Error::other(e),
155 backtrace: Some(Backtrace::capture()),
156 }
157}
158
159impl<'a> SigningKey<'a> {
160 fn new(raw_signer: &'a dyn RawSigningKey, public_key: PublicKey, user_id: UserId) -> Self {
163 Self {
164 raw_signer,
165 public_key,
166 user_id,
167 }
168 }
169
170 pub(crate) fn new_provisioned(raw_signer: &'a dyn RawSigningKey) -> Result<Self, crate::Error> {
185 let certificate = if let Some(cert) = raw_signer.certificate()?.as_ref() {
186 SignedPublicKey::from_bytes(Cursor::new(cert)).map_err(Error::Pgp)?
187 } else {
188 return Err(Error::OpenPpgCertificateMissing.into());
189 };
190 let user_id = if let Some(user_id) = certificate.details.users.first() {
191 user_id.clone().id
192 } else {
193 return Err(Error::OpenPpgUserIdsMissing {
194 fingerprint: certificate.fingerprint(),
195 }
196 .into());
197 };
198 Ok(Self::new(raw_signer, certificate.primary_key, user_id))
199 }
200
201 pub fn user_id(&self) -> &UserId {
209 &self.user_id
210 }
211}
212
213impl KeyDetails for SigningKey<'_> {
214 fn version(&self) -> KeyVersion {
215 self.public_key.version()
216 }
217
218 fn fingerprint(&self) -> Fingerprint {
219 self.public_key.fingerprint()
220 }
221
222 fn legacy_key_id(&self) -> KeyId {
223 self.public_key.legacy_key_id()
224 }
225
226 fn algorithm(&self) -> PublicKeyAlgorithm {
227 self.public_key.algorithm()
228 }
229
230 fn created_at(&self) -> Timestamp {
231 self.public_key.created_at()
232 }
233
234 fn legacy_v3_expiration_days(&self) -> Option<u16> {
235 self.public_key.legacy_v3_expiration_days()
236 }
237
238 fn public_params(&self) -> &PublicParams {
239 self.public_key.public_params()
240 }
241}
242
243impl RpgpSigningKey for SigningKey<'_> {
244 fn sign(
262 &self,
263 _key_pw: &Password,
264 hash: HashAlgorithm,
265 data: &[u8],
266 ) -> pgp::errors::Result<SignatureBytes> {
267 if hash != self.hash_alg() {
268 error!(
269 "Requested signing hash is different from the default supported, got {hash} expected {expected}",
270 expected = self.hash_alg()
271 );
272 return Err(to_rpgp_error(Error::UnsupportedHashAlgorithm {
273 actual: hash,
274 expected: self.hash_alg(),
275 }));
276 }
277 let sig = self.raw_signer.sign(data).map_err(|e| {
278 error!("RawSigner::sign failed: {e:?}");
279 to_rpgp_error(e)
280 })?;
281
282 Ok(SignatureBytes::Mpis(
283 sig.into_iter().map(|b| Mpi::from_slice(&b)).collect(),
284 ))
285 }
286
287 fn hash_alg(&self) -> HashAlgorithm {
293 HashAlgorithm::Sha512
294 }
295}
296
297pub fn generate_certificate<'notation_name, 'notation_value>(
310 raw_signer: &dyn RawSigningKey,
311 flags: OpenPgpKeyUsageFlags,
312 user_ids: &[OpenPgpUserId],
313 notations: &[Notation<'notation_name, 'notation_value>],
314 created_at: Timestamp,
315 version: OpenPgpVersion,
316) -> Result<Vec<u8>, crate::Error> {
317 if version != OpenPgpVersion::V4 {
318 return Err(crate::openpgp::Error::InvalidOpenPgpVersion(version.to_string()).into());
319 }
320
321 let (primary_user_id, user_ids) = {
322 if user_ids.is_empty() {
323 return Err(crate::openpgp::Error::OpenPgpUserIdMissing.into());
324 }
325
326 let user_ids = user_ids
327 .iter()
328 .map(|user_id| UserId::from_str(Default::default(), user_id))
329 .collect::<Result<Vec<UserId>, _>>()
330 .map_err(Error::Pgp)?;
331
332 (
334 user_ids
335 .first()
336 .expect("there to be at least one OpenPGP User ID")
337 .clone(),
338 user_ids,
339 )
340 };
341
342 let public_key = raw_signer.public()?.to_openpgp_public_key(created_at)?;
343
344 let signer = SigningKey::new(raw_signer, public_key.clone(), primary_user_id.clone());
345
346 let users = user_ids
347 .iter()
348 .map(|user_id| {
349 let config = {
352 let mut config = SignatureConfig::from_key(
353 &mut thread_rng(),
354 &signer,
355 SignatureType::CertPositive,
356 )
357 .map_err(Error::Pgp)?;
358
359 config.hashed_subpackets = vec![
360 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
361 .map_err(Error::Pgp)?,
362 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
363 .map_err(Error::Pgp)?,
364 Subpacket::regular(SubpacketData::KeyFlags(flags.clone().into()))
365 .map_err(Error::Pgp)?,
366 Subpacket::regular(SubpacketData::IsPrimary(user_id == &primary_user_id))
367 .map_err(Error::Pgp)?,
368 ];
369
370 for notation in notations.iter() {
371 config.hashed_subpackets.push(
372 Subpacket::regular(SubpacketData::Notation(PgpNotation {
373 readable: true,
374 name: notation.name.to_string().into(),
375 value: notation.value.to_string().into(),
376 }))
377 .map_err(Error::Pgp)?,
378 );
379 }
380
381 config.unhashed_subpackets = vec![
382 Subpacket::regular(SubpacketData::IssuerKeyId(public_key.legacy_key_id()))
383 .map_err(Error::Pgp)?,
384 ];
385
386 config
387 };
388
389 let sig = config
390 .sign_certification(
391 &signer,
392 &public_key,
393 &Password::empty(),
394 user_id.tag(),
395 &user_id,
396 )
397 .map_err(Error::Pgp)?;
398 Ok::<_, Error>(user_id.clone().into_signed(sig))
399 })
400 .collect::<Result<_, _>>()?;
401
402 let signed_pk = SignedPublicKey {
403 details: SignedKeyDetails {
404 users,
405 revocation_signatures: Vec::new(),
406 direct_signatures: Vec::new(),
407 user_attributes: Vec::new(),
408 },
409 primary_key: public_key,
410 public_subkeys: Vec::new(),
411 };
412
413 let buffer = {
414 let mut buffer = Vec::new();
415 signed_pk.to_writer(&mut buffer).map_err(Error::Pgp)?;
416 buffer
417 };
418 Ok(buffer)
419}
420
421pub fn tsk_to_private_key_import(
431 key: &SignedSecretKey,
432) -> Result<(PrivateKeyImport, KeyMechanism), crate::Error> {
433 if !key.secret_subkeys.is_empty() {
434 return Err(Error::OpenPgpTskContainsMultipleComponentKeys {
435 fingerprint: key.fingerprint(),
436 }
437 .into());
438 }
439 let SecretParams::Plain(secret) = key.primary_key.secret_params() else {
440 return Err(Error::OpenPgpTskIsPassphraseProtected {
441 fingerprint: key.fingerprint(),
442 }
443 .into());
444 };
445 Ok(match (secret, key.public_key().public_params()) {
446 (PlainSecretParams::RSA(secret), PublicParams::RSA(public)) => {
447 key_type_matches_length(
449 KeyType::Rsa,
450 Some(public.key.n().to_bytes_be().len() as u32 * 8),
451 )?;
452
453 let (_d, p, q, _u) = secret.to_bytes();
454
455 (
456 PrivateKeyImport::from_rsa(p, q, public.key.e().to_bytes_be().to_vec()),
457 KeyMechanism::RsaSignaturePkcs1,
458 )
459 }
460 (PlainSecretParams::ECDSA(secret_key), _) => {
461 let ec = if let PublicParams::ECDSA(pp) = key.primary_key.public_key().public_params() {
462 match pp {
463 EcdsaPublicParams::P256 { .. } => KeyType::EcP256,
464 EcdsaPublicParams::P384 { .. } => KeyType::EcP384,
465 EcdsaPublicParams::P521 { .. } => KeyType::EcP521,
466 pp => {
467 warn!("Unsupported ECDSA parameters: {pp:?}");
468 return Err(Error::UnsupportedKeyFormat {
469 context: "converting ECDSA key to private key import",
470 public_params: Box::new(key.public_key().public_params().clone()),
471 })?;
472 }
473 }
474 } else {
475 return Err(Error::UnsupportedKeyFormat {
476 context: "converting non-ECDSA key to private key import",
477 public_params: Box::new(key.public_key().public_params().clone()),
478 }
479 .into());
480 };
481
482 let bytes = match secret_key {
483 SecretKey::P256(secret_key) => secret_key.to_bytes().to_vec(),
484 SecretKey::P384(secret_key) => secret_key.to_bytes().to_vec(),
485 SecretKey::P521(secret_key) => secret_key.to_bytes().to_vec(),
486 SecretKey::Secp256k1(secret_key) => secret_key.to_bytes().to_vec(),
487 secret_key => {
488 warn!("Unsupported secret key parameters: {secret_key:?}");
489 return Err(Error::UnsupportedKeyFormat {
490 context: "converting unsupported ECDSA key to private key import",
491 public_params: Box::new(key.public_key().public_params().clone()),
492 })?;
493 }
494 };
495
496 (
497 PrivateKeyImport::from_raw_bytes(ec, bytes)?,
498 KeyMechanism::EcdsaSignature,
499 )
500 }
501 (PlainSecretParams::EdDSALegacy(EdDsaLegacySecretKey::Ed25519(bytes)), _) => (
502 PrivateKeyImport::from_raw_bytes(KeyType::Curve25519, bytes.as_bytes())?,
503 KeyMechanism::EdDsaSignature,
504 ),
505 (_, public_params) => {
506 return Err(Error::UnsupportedKeyFormat {
507 context: "converting unknown key format to private key import",
508 public_params: Box::new(public_params.clone()),
509 }
510 .into());
511 }
512 })
513}
514
515pub fn sign(raw_signer: &dyn RawSigningKey, message: &[u8]) -> Result<Vec<u8>, crate::Error> {
534 let signer = SigningKey::new_provisioned(raw_signer)?;
535
536 let mut sig_config =
537 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
538 sig_config.hashed_subpackets = vec![
539 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
540 .map_err(Error::Pgp)?,
541 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
542 .map_err(Error::Pgp)?,
543 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
544 .map_err(Error::Pgp)?,
545 ];
546
547 let mut hasher = sig_config
548 .hash_alg
549 .new_hasher()
550 .map_err(|source| Error::Pgp(to_rpgp_error(source)))?;
551 sig_config
552 .hash_data_to_sign(&mut hasher, message)
553 .map_err(Error::Pgp)?;
554
555 let len = sig_config
556 .hash_signature_data(&mut hasher)
557 .map_err(Error::Pgp)?;
558
559 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
560
561 let hash = &hasher.finalize()[..];
562
563 let signed_hash_value = [hash[0], hash[1]];
564 let raw_sig = signer
565 .sign(&Password::empty(), sig_config.hash_alg, hash)
566 .map_err(Error::Pgp)?;
567
568 let signature =
569 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
570
571 let mut out = vec![];
572 signature
573 .to_writer_with_header(&mut out)
574 .map_err(Error::Pgp)?;
575
576 Ok(out)
577}
578
579#[derive(Clone, Default)]
589struct Hasher(sha2::Sha512);
590
591impl DynDigest for Hasher {
592 fn update(&mut self, data: &[u8]) {
596 self.0.update(data);
597 }
598
599 fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
605 sha2::digest::DynDigest::finalize_into(self.0, buf).map_err(|_| InvalidBufferSize)?;
606 Ok(())
607 }
608
609 fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize> {
615 sha2::digest::DynDigest::finalize_into_reset(&mut self.0, out)
616 .map_err(|_| InvalidBufferSize)?;
617 Ok(())
618 }
619
620 fn reset(&mut self) {
622 sha2::digest::DynDigest::reset(&mut self.0)
623 }
624
625 fn output_size(&self) -> usize {
627 sha2::digest::DynDigest::output_size(&self.0)
628 }
629
630 fn box_clone(&self) -> Box<dyn DynDigest> {
632 Box::new(self.clone())
633 }
634}
635
636pub fn sign_hasher_state(
655 raw_signer: &dyn RawSigningKey,
656 state: sha2::Sha512,
657 notations: impl IntoIterator<Item = (String, String)>,
658) -> Result<String, crate::Error> {
659 let signer = SigningKey::new_provisioned(raw_signer)?;
660 let hasher = state.clone();
661
662 let file_hash = Box::new(hasher).finalize().to_vec();
663
664 let sig_config = {
665 let mut sig_config =
666 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
667 sig_config.hashed_subpackets = vec![
668 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
669 .map_err(Error::Pgp)?,
670 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
671 .map_err(Error::Pgp)?,
672 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
673 .map_err(Error::Pgp)?,
674 Subpacket::regular(SubpacketData::Notation(PgpNotation {
675 readable: false,
676 name: "data-digest@archlinux.org".into(),
677 value: file_hash.into(),
678 }))
679 .map_err(Error::Pgp)?,
680 Subpacket::regular(SubpacketData::SignersUserID(
681 signer.user_id().clone().into_bytes(),
682 ))
683 .map_err(Error::Pgp)?,
684 ];
685
686 for (name, value) in notations {
687 sig_config.hashed_subpackets.push(
688 Subpacket::regular(SubpacketData::Notation(PgpNotation {
689 readable: true,
690 name: name.into(),
691 value: value.into(),
692 }))
693 .map_err(Error::Pgp)?,
694 )
695 }
696 sig_config
697 };
698
699 let mut hasher = Box::new(Hasher(state.clone())) as Box<dyn DynDigest + Send>;
700
701 let len = sig_config
702 .hash_signature_data(&mut hasher)
703 .map_err(Error::Pgp)?;
704
705 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
706
707 let hash = &hasher.finalize()[..];
708
709 let signed_hash_value = [hash[0], hash[1]];
710
711 let raw_sig = signer
712 .sign(&Password::empty(), sig_config.hash_alg, hash)
713 .map_err(Error::Pgp)?;
714
715 let signature =
716 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
717
718 let signature = DetachedSignature { signature };
719 Ok(signature
720 .to_armored_string(ArmorOptions::default())
721 .map_err(Error::Pgp)?)
722}
723
724fn ecdsa_to_public_key(created_at: Timestamp, key: EcdsaPublicParams) -> Result<PublicKey, Error> {
735 Ok(PublicKey::from_inner(PubKeyInner::new(
736 KeyVersion::V4,
737 PublicKeyAlgorithm::ECDSA,
738 created_at,
739 None,
740 PublicParams::ECDSA(key),
741 )?)?)
742}
743
744impl RawPublicKey {
745 fn to_openpgp_public_key(&self, created_at: Timestamp) -> Result<PublicKey, Error> {
761 Ok(match self {
762 RawPublicKey::Rsa { modulus, exponent } => PublicKey::from_inner(PubKeyInner::new(
763 KeyVersion::V4,
764 PublicKeyAlgorithm::RSA,
765 created_at,
766 None,
767 PublicParams::RSA(RsaPublicParams {
768 key: RsaPublicKey::new(
769 BigUint::from_bytes_be(modulus),
770 BigUint::from_bytes_be(exponent),
771 )
772 .map_err(to_rpgp_error)?,
773 }),
774 )?)?,
775
776 RawPublicKey::Ed25519(pubkey) => PublicKey::from_inner(PubKeyInner::new(
777 KeyVersion::V4,
778 PublicKeyAlgorithm::EdDSALegacy,
779 created_at,
780 None,
781 PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 {
782 key: VerifyingKey::from_bytes(&pubkey[..].try_into().map_err(to_rpgp_error)?)
783 .map_err(to_rpgp_error)?,
784 }),
785 )?)?,
786
787 RawPublicKey::P256(pubkey) => ecdsa_to_public_key(
788 created_at,
789 EcdsaPublicParams::P256 {
790 key: P256PublicKey::from_sec1_bytes(pubkey)?,
791 },
792 )?,
793
794 RawPublicKey::P384(pubkey) => ecdsa_to_public_key(
795 created_at,
796 EcdsaPublicParams::P384 {
797 key: P384PublicKey::from_sec1_bytes(pubkey)?,
798 },
799 )?,
800
801 RawPublicKey::P521(pubkey) => ecdsa_to_public_key(
802 created_at,
803 EcdsaPublicParams::P521 {
804 key: P521PublicKey::from_sec1_bytes(pubkey)?,
805 },
806 )?,
807 })
808 }
809}
810
811pub fn extract_certificate(key: SignedSecretKey) -> Result<Vec<u8>, crate::Error> {
824 let public: SignedPublicKey = key.into();
825 let mut buffer = vec![];
826 public.to_writer(&mut buffer).map_err(Error::Pgp)?;
827 Ok(buffer)
828}
829
830#[cfg(test)]
831mod tests {
832 use std::assert_matches;
833
834 use ed25519_dalek::{Signer, SigningKey};
835 use pgp::{
836 composed::{KeyType as ComposedKeyType, SecretKeyParamsBuilder},
837 crypto::ecc_curve::ECCCurve,
838 types::{EcdsaPublicParams, PublicParams},
839 };
840 use rand::{Rng, SeedableRng, rng, rngs::ChaCha20Rng};
841 use rsa_0_9_for_rpgp::rand_core::OsRng;
842 use testresult::TestResult;
843
844 use super::*;
845
846 #[test]
847 fn convert_ed25519_to_pgp() -> TestResult {
848 let hsm_key = RawPublicKey::Ed25519(vec![
849 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29, 198,
850 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10,
851 ]);
852
853 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
854 let PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 { key }) =
855 pgp_key.public_params()
856 else {
857 panic!("Wrong type of public params");
858 };
859 assert_eq!(
860 key.to_bytes(),
861 [
862 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29,
863 198, 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10
864 ]
865 );
866
867 Ok(())
868 }
869
870 #[test]
871 fn convert_p256_to_pgp() -> TestResult {
872 let hsm_key = RawPublicKey::P256(vec![
873 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130, 169,
874 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240, 240, 134,
875 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122, 89, 2, 180, 2,
876 237, 15, 248, 104, 83, 142, 22, 185, 133,
877 ]);
878 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
879 let PublicParams::ECDSA(EcdsaPublicParams::P256 { key, .. }) = pgp_key.public_params()
880 else {
881 panic!("Wrong type of public params");
882 };
883 assert_eq!(
884 key.to_sec1_bytes().to_vec(),
885 [
886 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130,
887 169, 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240,
888 240, 134, 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122,
889 89, 2, 180, 2, 237, 15, 248, 104, 83, 142, 22, 185, 133
890 ]
891 );
892
893 Ok(())
894 }
895
896 #[test]
897 fn convert_p384_to_pgp() -> TestResult {
898 let hsm_key = RawPublicKey::P384(vec![
899 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72, 250,
900 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8, 66, 117,
901 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8, 75, 151, 252,
902 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82, 134, 134, 6, 17,
903 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139, 217, 90, 220, 239, 191,
904 148,
905 ]);
906 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
907 let PublicParams::ECDSA(EcdsaPublicParams::P384 { key, .. }) = pgp_key.public_params()
908 else {
909 panic!("Wrong type of public params");
910 };
911 assert_eq!(
912 key.to_sec1_bytes().to_vec(),
913 [
914 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72,
915 250, 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8,
916 66, 117, 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8,
917 75, 151, 252, 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82,
918 134, 134, 6, 17, 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139,
919 217, 90, 220, 239, 191, 148
920 ]
921 );
922
923 Ok(())
924 }
925
926 #[test]
927 fn convert_p521_to_pgp() -> TestResult {
928 let hsm_key = RawPublicKey::P521(vec![
929 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211, 118,
930 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96, 102, 55,
931 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26, 190, 40, 157,
932 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243, 67, 14, 159, 46,
933 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76, 198, 240, 32, 108, 48,
934 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10, 65, 118, 233, 79, 179, 90,
935 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102, 113, 26, 103, 127, 234, 47, 81,
936 ]);
937 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
938 let PublicParams::ECDSA(EcdsaPublicParams::P521 { key, .. }) = pgp_key.public_params()
939 else {
940 panic!("Wrong type of public params");
941 };
942 assert_eq!(
943 key.to_sec1_bytes().to_vec(),
944 [
945 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211,
946 118, 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96,
947 102, 55, 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26,
948 190, 40, 157, 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243,
949 67, 14, 159, 46, 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76,
950 198, 240, 32, 108, 48, 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10,
951 65, 118, 233, 79, 179, 90, 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102,
952 113, 26, 103, 127, 234, 47, 81
953 ]
954 );
955
956 Ok(())
957 }
958
959 #[test]
960 fn convert_rsa_to_pgp() -> TestResult {
961 let hsm_key = RawPublicKey::Rsa {
962 modulus: vec![
963 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
964 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
965 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
966 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
967 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
968 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
969 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
970 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
971 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
972 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
973 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
974 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
975 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
976 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
977 59, 161, 187,
978 ],
979 exponent: vec![1, 0, 1],
980 };
981 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
982 let PublicParams::RSA(public) = pgp_key.public_params() else {
983 panic!("Wrong type of public params");
984 };
985 assert_eq!(public.key.e().to_bytes_be(), [1, 0, 1]);
986 assert_eq!(
987 public.key.n().to_bytes_be(),
988 [
989 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
990 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
991 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
992 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
993 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
994 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
995 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
996 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
997 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
998 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
999 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
1000 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
1001 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
1002 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
1003 59, 161, 187
1004 ]
1005 );
1006
1007 Ok(())
1008 }
1009
1010 #[cfg(feature = "nethsm")]
1012 mod nethsm {
1013 use std::fs::File;
1014
1015 use base64ct::{Base64, Encoding as _};
1016 use nethsm_sdk_rs::models::KeyPrivateData;
1017
1018 use super::*;
1019
1020 #[test]
1021 fn private_key_import_ed25199_is_correctly_zero_padded() -> TestResult {
1022 let key = SignedSecretKey::from_armor_single(File::open(
1023 "tests/fixtures/ed25519-key-with-31-byte-private-key-scalar.asc",
1024 )?)?
1025 .0;
1026
1027 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
1028
1029 let data = Base64::decode_vec(&import.data.unwrap())?;
1030
1031 assert_eq!(data.len(), 32);
1034 assert_eq!(data[0], 0x00);
1035
1036 Ok(())
1037 }
1038
1039 #[test]
1040 #[cfg(feature = "nethsm")]
1041 fn private_key_import_rsa_key_with_nonstandard_moduli_is_read_correctly() -> TestResult {
1042 let key = SignedSecretKey::from_armor_single(File::open(
1043 "tests/fixtures/rsa-key-with-modulus-e-257.asc",
1044 )?)?
1045 .0;
1046
1047 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
1048
1049 let data = Base64::decode_vec(&import.public_exponent.unwrap())?;
1050
1051 assert_eq!(data, vec![0x01, 0x01]); Ok(())
1055 }
1056 }
1057
1058 struct Ed25519SoftKey {
1060 signing_key: SigningKey,
1062
1063 certificate: Option<Vec<u8>>,
1065 }
1066
1067 impl Ed25519SoftKey {
1068 fn new() -> Self {
1072 Self {
1073 signing_key: SigningKey::generate(&mut ChaCha20Rng::from_rng(&mut rng())),
1077 certificate: None,
1078 }
1079 }
1080 }
1081
1082 impl RawSigningKey for Ed25519SoftKey {
1083 fn key_id(&self) -> String {
1085 "Software key".into()
1086 }
1087
1088 fn sign(&self, digest: &[u8]) -> Result<Vec<Vec<u8>>, crate::Error> {
1094 let signature = self.signing_key.sign(digest);
1095 Ok(vec![signature.r_bytes().into(), signature.s_bytes().into()])
1096 }
1097
1098 fn certificate(&self) -> Result<Option<Vec<u8>>, crate::Error> {
1104 Ok(self.certificate.clone())
1105 }
1106
1107 fn public(&self) -> Result<RawPublicKey, crate::Error> {
1113 Ok(RawPublicKey::Ed25519(
1114 self.signing_key.verifying_key().to_bytes().into(),
1115 ))
1116 }
1117 }
1118
1119 #[test]
1120 fn sign_dummy() -> TestResult {
1121 let mut raw_signer = Ed25519SoftKey::new();
1122
1123 let cert = generate_certificate(
1124 &raw_signer,
1125 Default::default(),
1126 &[OpenPgpUserId::new("test".into())?],
1127 Default::default(),
1128 Timestamp::now(),
1129 Default::default(),
1130 )?;
1131
1132 raw_signer.certificate = Some(cert);
1133
1134 let mut data_to_sign = [0; 32];
1135 rng().fill_bytes(&mut data_to_sign);
1136
1137 let signature = sign(&raw_signer, &data_to_sign)?;
1138 assert!(!signature.is_empty());
1139
1140 Ok(())
1141 }
1142
1143 #[test]
1146 fn check_empty_user_ids() -> TestResult {
1147 use crate::signer::error::Error;
1148 use crate::signer::openpgp::SigningKey;
1149
1150 let mut raw_signer = Ed25519SoftKey::new();
1151
1152 let cert = generate_certificate(
1154 &raw_signer,
1155 Default::default(),
1156 &[OpenPgpUserId::new("test".into())?],
1157 Default::default(),
1158 Timestamp::now(),
1159 Default::default(),
1160 )?;
1161
1162 let (cert, cert_fingerprint) = {
1164 let mut cert = SignedPublicKey::from_bytes(Cursor::new(cert))?;
1165 cert.details.users = vec![];
1166 (cert.to_bytes()?, cert.fingerprint())
1167 };
1168
1169 raw_signer.certificate = Some(cert);
1170
1171 assert_matches!(
1172 SigningKey::new_provisioned(&raw_signer),
1173 Err(crate::Error::Signer(Error::OpenPpgUserIdsMissing { fingerprint })) if fingerprint == cert_fingerprint
1174 );
1175
1176 Ok(())
1177 }
1178
1179 #[test]
1180 fn estimate_certificate_size() -> TestResult {
1181 let cert = generate_certificate(
1182 &EmptyEd25519Signer,
1183 Default::default(),
1184 &[OpenPgpUserId::new("test".into())?],
1185 &[],
1186 Timestamp::now(),
1187 Default::default(),
1188 )?;
1189
1190 assert_eq!(cert.len(), 120);
1191
1192 let cert = generate_certificate(
1194 &EmptyEd25519Signer,
1195 Default::default(),
1196 &[OpenPgpUserId::new("test test".into())?],
1197 &[],
1198 Timestamp::now(),
1199 Default::default(),
1200 )?;
1201
1202 assert_eq!(cert.len(), 125);
1204
1205 Ok(())
1206 }
1207
1208 #[rstest::rstest]
1209 #[case::p256(ECCCurve::P256, KeyType::EcP256)]
1210 #[case::p384(ECCCurve::P384, KeyType::EcP384)]
1211 #[case::p521(ECCCurve::P521, KeyType::EcP521)]
1212 fn import_ecdsa(#[case] pgp_curve: ECCCurve, #[case] expected_type: KeyType) -> TestResult {
1213 let params = SecretKeyParamsBuilder::default()
1214 .key_type(ComposedKeyType::ECDSA(pgp_curve))
1215 .can_sign(true)
1216 .build()?;
1217
1218 let rng = OsRng;
1219
1220 let key = params.generate(rng)?;
1221 let actual_type = tsk_to_private_key_import(&key)?.0.key_type();
1222 assert_eq!(actual_type, expected_type);
1223
1224 Ok(())
1225 }
1226
1227 #[test]
1228 fn test_unsupported_ecdsa_curve() -> TestResult {
1229 let key = SecretKeyParamsBuilder::default()
1230 .key_type(ComposedKeyType::ECDSA(ECCCurve::Secp256k1))
1231 .can_sign(true)
1232 .build()?
1233 .generate(OsRng)?;
1234
1235 assert!(tsk_to_private_key_import(&key).is_err());
1236
1237 Ok(())
1238 }
1239}