1use std::{backtrace::Backtrace, io::Cursor};
4
5use digest::DynDigest;
6use ed25519_dalek::VerifyingKey;
7use log::{error, warn};
8pub use pgp::composed::{Deserializable, SignedSecretKey};
10pub use pgp::types::Timestamp;
11use pgp::{
12 composed::{
13 ArmorOptions,
14 DetachedSignature,
15 KeyDetails as ComposedKeyDetails,
16 SignedPublicKey,
17 },
18 crypto::{
19 ecdsa::SecretKey,
20 eddsa_legacy::SecretKey as EdDsaLegacySecretKey,
21 hash::HashAlgorithm,
22 public_key::PublicKeyAlgorithm,
23 },
24 packet::{
25 Notation,
26 PacketTrait,
27 PubKeyInner,
28 PublicKey,
29 Signature,
30 SignatureConfig,
31 SignatureType,
32 Subpacket,
33 SubpacketData,
34 UserId,
35 },
36 ser::Serialize,
37 types::{
38 CompressionAlgorithm,
39 EcdsaPublicParams,
40 EddsaLegacyPublicParams,
41 Fingerprint,
42 KeyDetails,
43 KeyId,
44 KeyVersion,
45 Mpi,
46 Password,
47 PlainSecretParams,
48 PublicParams,
49 RsaPublicParams,
50 SecretParams,
51 SignatureBytes,
52 SigningKey as RpgpSigningKey,
53 },
54};
55use rand::thread_rng;
56use rsa::{BigUint, RsaPublicKey, traits::PublicKeyParts as _};
57use sha2::digest::Digest as _;
58
59use crate::{
60 key::{KeyMechanism, KeyType, PrivateKeyImport, key_type_matches_length},
61 openpgp::{OpenPgpKeyUsageFlags, OpenPgpUserId, OpenPgpVersion},
62 signer::{
63 error::Error,
64 traits::{RawPublicKey, RawSigningKey},
65 },
66};
67
68pub(crate) struct SigningKey<'a> {
73 public_key: PublicKey,
74 raw_signer: &'a dyn RawSigningKey,
75 user_id: UserId,
76}
77
78impl std::fmt::Debug for SigningKey<'_> {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 f.debug_struct("SigningKey")
81 .field("public_key", &self.public_key)
82 .finish()
83 }
84}
85
86#[inline]
92fn to_rpgp_error(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> pgp::errors::Error {
93 pgp::errors::Error::IO {
94 source: std::io::Error::other(e),
95 backtrace: Some(Backtrace::capture()),
96 }
97}
98
99impl<'a> SigningKey<'a> {
100 fn new(raw_signer: &'a dyn RawSigningKey, public_key: PublicKey, user_id: UserId) -> Self {
103 Self {
104 raw_signer,
105 public_key,
106 user_id,
107 }
108 }
109
110 pub(crate) fn new_provisioned(raw_signer: &'a dyn RawSigningKey) -> Result<Self, crate::Error> {
125 let certificate = if let Some(cert) = raw_signer.certificate()?.as_ref() {
126 SignedPublicKey::from_bytes(Cursor::new(cert)).map_err(Error::Pgp)?
127 } else {
128 return Err(Error::OpenPpgCertificateMissing.into());
129 };
130 let user_id = if let Some(user_id) = certificate.details.users.first() {
131 user_id.clone().id
132 } else {
133 return Err(Error::OpenPpgUserIdsMissing {
134 fingerprint: certificate.fingerprint(),
135 }
136 .into());
137 };
138 Ok(Self::new(raw_signer, certificate.primary_key, user_id))
139 }
140
141 pub fn user_id(&self) -> &UserId {
149 &self.user_id
150 }
151}
152
153impl KeyDetails for SigningKey<'_> {
154 fn version(&self) -> KeyVersion {
155 self.public_key.version()
156 }
157
158 fn fingerprint(&self) -> Fingerprint {
159 self.public_key.fingerprint()
160 }
161
162 fn legacy_key_id(&self) -> KeyId {
163 self.public_key.legacy_key_id()
164 }
165
166 fn algorithm(&self) -> PublicKeyAlgorithm {
167 self.public_key.algorithm()
168 }
169
170 fn created_at(&self) -> Timestamp {
171 self.public_key.created_at()
172 }
173
174 fn legacy_v3_expiration_days(&self) -> Option<u16> {
175 self.public_key.legacy_v3_expiration_days()
176 }
177
178 fn public_params(&self) -> &PublicParams {
179 self.public_key.public_params()
180 }
181}
182
183impl RpgpSigningKey for SigningKey<'_> {
184 fn sign(
202 &self,
203 _key_pw: &Password,
204 hash: HashAlgorithm,
205 data: &[u8],
206 ) -> pgp::errors::Result<SignatureBytes> {
207 if hash != self.hash_alg() {
208 error!(
209 "Requested signing hash is different from the default supported, got {hash} expected {expected}",
210 expected = self.hash_alg()
211 );
212 return Err(to_rpgp_error(Error::UnsupportedHashAlgorithm {
213 actual: hash,
214 expected: self.hash_alg(),
215 }));
216 }
217 let sig = self.raw_signer.sign(data).map_err(|e| {
218 error!("RawSigner::sign failed: {e:?}");
219 to_rpgp_error(e)
220 })?;
221
222 Ok(SignatureBytes::Mpis(
223 sig.into_iter().map(|b| Mpi::from_slice(&b)).collect(),
224 ))
225 }
226
227 fn hash_alg(&self) -> HashAlgorithm {
233 HashAlgorithm::Sha512
234 }
235}
236
237pub fn add_certificate(
250 raw_signer: &dyn RawSigningKey,
251 flags: OpenPgpKeyUsageFlags,
252 user_ids: &[OpenPgpUserId],
253 created_at: Timestamp,
254 version: OpenPgpVersion,
255) -> Result<Vec<u8>, crate::Error> {
256 if version != OpenPgpVersion::V4 {
257 return Err(crate::openpgp::Error::InvalidOpenPgpVersion(version.to_string()).into());
258 }
259
260 if user_ids.is_empty() {
261 return Err(crate::openpgp::Error::OpenPgpUserIdMissing.into());
262 }
263
264 let (primary_user_id, user_ids) = {
265 let mut user_ids = user_ids
266 .iter()
267 .map(|user_id| UserId::from_str(Default::default(), user_id))
268 .collect::<Result<Vec<UserId>, _>>()
269 .map_err(Error::Pgp)?;
270
271 (user_ids.remove(0), user_ids)
272 };
273
274 let public_key = raw_signer.public()?.to_openpgp_public_key(created_at)?;
275 let signer = SigningKey::new(raw_signer, public_key.clone(), primary_user_id.clone());
276
277 let signed_pk = SignedPublicKey {
278 details: ComposedKeyDetails::new(
279 Some(primary_user_id),
280 user_ids,
281 vec![],
282 flags.into(),
283 Default::default(),
284 Default::default(),
285 Default::default(),
286 vec![CompressionAlgorithm::Uncompressed].into(),
287 vec![].into(),
288 )
289 .sign(thread_rng(), &signer, &public_key, &Password::empty())
290 .map_err(Error::Pgp)?,
291 primary_key: public_key,
292 public_subkeys: vec![],
293 };
294
295 let mut buffer = vec![];
296 signed_pk.to_writer(&mut buffer).map_err(Error::Pgp)?;
297 Ok(buffer)
298}
299
300pub fn tsk_to_private_key_import(
310 key: &SignedSecretKey,
311) -> Result<(PrivateKeyImport, KeyMechanism), crate::Error> {
312 if !key.secret_subkeys.is_empty() {
313 return Err(Error::OpenPgpTskContainsMultipleComponentKeys {
314 fingerprint: key.fingerprint(),
315 }
316 .into());
317 }
318 let SecretParams::Plain(secret) = key.primary_key.secret_params() else {
319 return Err(Error::OpenPgpTskIsPassphraseProtected {
320 fingerprint: key.fingerprint(),
321 }
322 .into());
323 };
324 Ok(match (secret, key.public_key().public_params()) {
325 (PlainSecretParams::RSA(secret), PublicParams::RSA(public)) => {
326 key_type_matches_length(
328 KeyType::Rsa,
329 Some(public.key.n().to_bytes_be().len() as u32 * 8),
330 )?;
331
332 let (_d, p, q, _u) = secret.to_bytes();
333
334 (
335 PrivateKeyImport::from_rsa(p, q, public.key.e().to_bytes_be().to_vec()),
336 KeyMechanism::RsaSignaturePkcs1,
337 )
338 }
339 (PlainSecretParams::ECDSA(secret_key), _) => {
340 let ec = if let PublicParams::ECDSA(pp) = key.primary_key.public_key().public_params() {
341 match pp {
342 EcdsaPublicParams::P256 { .. } => KeyType::EcP256,
343 EcdsaPublicParams::P384 { .. } => KeyType::EcP384,
344 EcdsaPublicParams::P521 { .. } => KeyType::EcP521,
345 pp => {
346 warn!("Unsupported ECDSA parameters: {pp:?}");
347 return Err(Error::UnsupportedKeyFormat {
348 context: "converting ECDSA key to private key import",
349 public_params: Box::new(key.public_key().public_params().clone()),
350 })?;
351 }
352 }
353 } else {
354 return Err(Error::UnsupportedKeyFormat {
355 context: "converting non-ECDSA key to private key import",
356 public_params: Box::new(key.public_key().public_params().clone()),
357 }
358 .into());
359 };
360
361 let bytes = match secret_key {
362 SecretKey::P256(secret_key) => secret_key.to_bytes().to_vec(),
363 SecretKey::P384(secret_key) => secret_key.to_bytes().to_vec(),
364 SecretKey::P521(secret_key) => secret_key.to_bytes().to_vec(),
365 SecretKey::Secp256k1(secret_key) => secret_key.to_bytes().to_vec(),
366 secret_key => {
367 warn!("Unsupported secret key parameters: {secret_key:?}");
368 return Err(Error::UnsupportedKeyFormat {
369 context: "converting unsupported ECDSA key to private key import",
370 public_params: Box::new(key.public_key().public_params().clone()),
371 })?;
372 }
373 };
374
375 (
376 PrivateKeyImport::from_raw_bytes(ec, bytes)?,
377 KeyMechanism::EcdsaSignature,
378 )
379 }
380 (PlainSecretParams::EdDSALegacy(EdDsaLegacySecretKey::Ed25519(bytes)), _) => (
381 PrivateKeyImport::from_raw_bytes(KeyType::Curve25519, bytes.as_bytes())?,
382 KeyMechanism::EdDsaSignature,
383 ),
384 (_, public_params) => {
385 return Err(Error::UnsupportedKeyFormat {
386 context: "converting unknown key format to private key import",
387 public_params: Box::new(public_params.clone()),
388 }
389 .into());
390 }
391 })
392}
393
394pub fn sign(raw_signer: &dyn RawSigningKey, message: &[u8]) -> Result<Vec<u8>, crate::Error> {
413 let signer = SigningKey::new_provisioned(raw_signer)?;
414
415 let mut sig_config =
416 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
417 sig_config.hashed_subpackets = vec![
418 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
419 .map_err(Error::Pgp)?,
420 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
421 .map_err(Error::Pgp)?,
422 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
423 .map_err(Error::Pgp)?,
424 ];
425
426 let mut hasher = sig_config
427 .hash_alg
428 .new_hasher()
429 .map_err(|source| Error::Pgp(to_rpgp_error(source)))?;
430 sig_config
431 .hash_data_to_sign(&mut hasher, message)
432 .map_err(Error::Pgp)?;
433
434 let len = sig_config
435 .hash_signature_data(&mut hasher)
436 .map_err(Error::Pgp)?;
437
438 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
439
440 let hash = &hasher.finalize()[..];
441
442 let signed_hash_value = [hash[0], hash[1]];
443 let raw_sig = signer
444 .sign(&Password::empty(), sig_config.hash_alg, hash)
445 .map_err(Error::Pgp)?;
446
447 let signature =
448 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
449
450 let mut out = vec![];
451 signature
452 .to_writer_with_header(&mut out)
453 .map_err(Error::Pgp)?;
454
455 Ok(out)
456}
457
458#[derive(Clone, Default)]
468struct Hasher(sha2::Sha512);
469
470impl DynDigest for Hasher {
471 fn update(&mut self, data: &[u8]) {
475 self.0.update(data);
476 }
477
478 fn finalize_into(self, buf: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
484 sha2::digest::DynDigest::finalize_into(self.0, buf)
485 .map_err(|_| digest::InvalidBufferSize)?;
486 Ok(())
487 }
488
489 fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
495 sha2::digest::DynDigest::finalize_into_reset(&mut self.0, out)
496 .map_err(|_| digest::InvalidBufferSize)?;
497 Ok(())
498 }
499
500 fn reset(&mut self) {
502 sha2::digest::DynDigest::reset(&mut self.0)
503 }
504
505 fn output_size(&self) -> usize {
507 sha2::digest::DynDigest::output_size(&self.0)
508 }
509
510 fn box_clone(&self) -> Box<dyn DynDigest> {
512 Box::new(self.clone())
513 }
514}
515
516pub fn sign_hasher_state(
535 raw_signer: &dyn RawSigningKey,
536 state: sha2::Sha512,
537) -> Result<String, crate::Error> {
538 let signer = SigningKey::new_provisioned(raw_signer)?;
539 let hasher = state.clone();
540
541 let file_hash = Box::new(hasher).finalize().to_vec();
542
543 let sig_config = {
544 let mut sig_config =
545 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
546 sig_config.hashed_subpackets = vec![
547 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
548 .map_err(Error::Pgp)?,
549 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
550 .map_err(Error::Pgp)?,
551 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
552 .map_err(Error::Pgp)?,
553 Subpacket::regular(SubpacketData::Notation(Notation {
554 readable: false,
555 name: "data-digest@archlinux.org".into(),
556 value: file_hash.into(),
557 }))
558 .map_err(Error::Pgp)?,
559 Subpacket::regular(SubpacketData::SignersUserID(
560 signer.user_id().clone().into_bytes(),
561 ))
562 .map_err(Error::Pgp)?,
563 ];
564 sig_config
565 };
566
567 let mut hasher = Box::new(Hasher(state.clone())) as Box<dyn DynDigest + Send>;
568
569 let len = sig_config
570 .hash_signature_data(&mut hasher)
571 .map_err(Error::Pgp)?;
572
573 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
574
575 let hash = &hasher.finalize()[..];
576
577 let signed_hash_value = [hash[0], hash[1]];
578
579 let raw_sig = signer
580 .sign(&Password::empty(), sig_config.hash_alg, hash)
581 .map_err(Error::Pgp)?;
582
583 let signature =
584 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
585
586 let signature = DetachedSignature { signature };
587 Ok(signature
588 .to_armored_string(ArmorOptions::default())
589 .map_err(Error::Pgp)?)
590}
591
592fn ecdsa_to_public_key(created_at: Timestamp, key: EcdsaPublicParams) -> Result<PublicKey, Error> {
603 Ok(PublicKey::from_inner(PubKeyInner::new(
604 KeyVersion::V4,
605 PublicKeyAlgorithm::ECDSA,
606 created_at,
607 None,
608 PublicParams::ECDSA(key),
609 )?)?)
610}
611
612impl RawPublicKey {
613 fn to_openpgp_public_key(&self, created_at: Timestamp) -> Result<PublicKey, Error> {
629 Ok(match self {
630 RawPublicKey::Rsa { modulus, exponent } => PublicKey::from_inner(PubKeyInner::new(
631 KeyVersion::V4,
632 PublicKeyAlgorithm::RSA,
633 created_at,
634 None,
635 PublicParams::RSA(RsaPublicParams {
636 key: RsaPublicKey::new(
637 BigUint::from_bytes_be(modulus),
638 BigUint::from_bytes_be(exponent),
639 )
640 .map_err(to_rpgp_error)?,
641 }),
642 )?)?,
643
644 RawPublicKey::Ed25519(pubkey) => PublicKey::from_inner(PubKeyInner::new(
645 KeyVersion::V4,
646 PublicKeyAlgorithm::EdDSALegacy,
647 created_at,
648 None,
649 PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 {
650 key: VerifyingKey::from_bytes(&pubkey[..].try_into().map_err(to_rpgp_error)?)
651 .map_err(to_rpgp_error)?,
652 }),
653 )?)?,
654
655 RawPublicKey::P256(pubkey) => ecdsa_to_public_key(
656 created_at,
657 EcdsaPublicParams::P256 {
658 key: p256::PublicKey::from_sec1_bytes(pubkey)?,
659 },
660 )?,
661
662 RawPublicKey::P384(pubkey) => ecdsa_to_public_key(
663 created_at,
664 EcdsaPublicParams::P384 {
665 key: p384::PublicKey::from_sec1_bytes(pubkey)?,
666 },
667 )?,
668
669 RawPublicKey::P521(pubkey) => ecdsa_to_public_key(
670 created_at,
671 EcdsaPublicParams::P521 {
672 key: p521::PublicKey::from_sec1_bytes(pubkey)?,
673 },
674 )?,
675 })
676 }
677}
678
679pub fn extract_certificate(key: SignedSecretKey) -> Result<Vec<u8>, crate::Error> {
692 let public: SignedPublicKey = key.into();
693 let mut buffer = vec![];
694 public.to_writer(&mut buffer).map_err(Error::Pgp)?;
695 Ok(buffer)
696}
697
698#[cfg(test)]
699mod tests {
700 use std::assert_matches;
701
702 use ed25519_dalek::{Signer, SigningKey};
703 use pgp::{
704 composed::{KeyType as ComposedKeyType, SecretKeyParamsBuilder},
705 crypto::ecc_curve::ECCCurve,
706 types::{EcdsaPublicParams, PublicParams},
707 };
708 use rand::RngCore;
709 use rsa::rand_core::OsRng;
710 use testresult::TestResult;
711
712 use super::*;
713
714 #[test]
715 fn convert_ed25519_to_pgp() -> TestResult {
716 let hsm_key = RawPublicKey::Ed25519(vec![
717 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29, 198,
718 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10,
719 ]);
720
721 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
722 let PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 { key }) =
723 pgp_key.public_params()
724 else {
725 panic!("Wrong type of public params");
726 };
727 assert_eq!(
728 key.to_bytes(),
729 [
730 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29,
731 198, 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10
732 ]
733 );
734
735 Ok(())
736 }
737
738 #[test]
739 fn convert_p256_to_pgp() -> TestResult {
740 let hsm_key = RawPublicKey::P256(vec![
741 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130, 169,
742 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240, 240, 134,
743 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122, 89, 2, 180, 2,
744 237, 15, 248, 104, 83, 142, 22, 185, 133,
745 ]);
746 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
747 let PublicParams::ECDSA(EcdsaPublicParams::P256 { key, .. }) = pgp_key.public_params()
748 else {
749 panic!("Wrong type of public params");
750 };
751 assert_eq!(
752 key.to_sec1_bytes().to_vec(),
753 [
754 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130,
755 169, 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240,
756 240, 134, 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122,
757 89, 2, 180, 2, 237, 15, 248, 104, 83, 142, 22, 185, 133
758 ]
759 );
760
761 Ok(())
762 }
763
764 #[test]
765 fn convert_p384_to_pgp() -> TestResult {
766 let hsm_key = RawPublicKey::P384(vec![
767 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72, 250,
768 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8, 66, 117,
769 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8, 75, 151, 252,
770 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82, 134, 134, 6, 17,
771 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139, 217, 90, 220, 239, 191,
772 148,
773 ]);
774 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
775 let PublicParams::ECDSA(EcdsaPublicParams::P384 { key, .. }) = pgp_key.public_params()
776 else {
777 panic!("Wrong type of public params");
778 };
779 assert_eq!(
780 key.to_sec1_bytes().to_vec(),
781 [
782 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72,
783 250, 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8,
784 66, 117, 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8,
785 75, 151, 252, 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82,
786 134, 134, 6, 17, 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139,
787 217, 90, 220, 239, 191, 148
788 ]
789 );
790
791 Ok(())
792 }
793
794 #[test]
795 fn convert_p521_to_pgp() -> TestResult {
796 let hsm_key = RawPublicKey::P521(vec![
797 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211, 118,
798 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96, 102, 55,
799 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26, 190, 40, 157,
800 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243, 67, 14, 159, 46,
801 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76, 198, 240, 32, 108, 48,
802 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10, 65, 118, 233, 79, 179, 90,
803 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102, 113, 26, 103, 127, 234, 47, 81,
804 ]);
805 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
806 let PublicParams::ECDSA(EcdsaPublicParams::P521 { key, .. }) = pgp_key.public_params()
807 else {
808 panic!("Wrong type of public params");
809 };
810 assert_eq!(
811 key.to_sec1_bytes().to_vec(),
812 [
813 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211,
814 118, 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96,
815 102, 55, 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26,
816 190, 40, 157, 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243,
817 67, 14, 159, 46, 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76,
818 198, 240, 32, 108, 48, 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10,
819 65, 118, 233, 79, 179, 90, 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102,
820 113, 26, 103, 127, 234, 47, 81
821 ]
822 );
823
824 Ok(())
825 }
826
827 #[test]
828 fn convert_rsa_to_pgp() -> TestResult {
829 let hsm_key = RawPublicKey::Rsa {
830 modulus: vec![
831 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
832 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
833 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
834 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
835 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
836 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
837 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
838 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
839 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
840 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
841 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
842 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
843 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
844 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
845 59, 161, 187,
846 ],
847 exponent: vec![1, 0, 1],
848 };
849 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
850 let PublicParams::RSA(public) = pgp_key.public_params() else {
851 panic!("Wrong type of public params");
852 };
853 assert_eq!(public.key.e().to_bytes_be(), [1, 0, 1]);
854 assert_eq!(
855 public.key.n().to_bytes_be(),
856 [
857 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
858 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
859 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
860 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
861 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
862 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
863 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
864 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
865 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
866 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
867 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
868 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
869 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
870 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
871 59, 161, 187
872 ]
873 );
874
875 Ok(())
876 }
877
878 #[cfg(feature = "nethsm")]
880 mod nethsm {
881 use std::fs::File;
882
883 use base64ct::{Base64, Encoding as _};
884 use nethsm_sdk_rs::models::KeyPrivateData;
885
886 use super::*;
887
888 #[test]
889 fn private_key_import_ed25199_is_correctly_zero_padded() -> TestResult {
890 let key = SignedSecretKey::from_armor_single(File::open(
891 "tests/fixtures/ed25519-key-with-31-byte-private-key-scalar.asc",
892 )?)?
893 .0;
894
895 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
896
897 let data = Base64::decode_vec(&import.data.unwrap())?;
898
899 assert_eq!(data.len(), 32);
902 assert_eq!(data[0], 0x00);
903
904 Ok(())
905 }
906
907 #[test]
908 #[cfg(feature = "nethsm")]
909 fn private_key_import_rsa_key_with_nonstandard_moduli_is_read_correctly() -> TestResult {
910 let key = SignedSecretKey::from_armor_single(File::open(
911 "tests/fixtures/rsa-key-with-modulus-e-257.asc",
912 )?)?
913 .0;
914
915 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
916
917 let data = Base64::decode_vec(&import.public_exponent.unwrap())?;
918
919 assert_eq!(data, vec![0x01, 0x01]); Ok(())
923 }
924 }
925
926 struct Ed25519SoftKey {
928 signing_key: SigningKey,
930
931 certificate: Option<Vec<u8>>,
933 }
934
935 impl Ed25519SoftKey {
936 fn new() -> Self {
940 Self {
941 signing_key: SigningKey::generate(&mut OsRng),
944 certificate: None,
945 }
946 }
947 }
948
949 impl RawSigningKey for Ed25519SoftKey {
950 fn key_id(&self) -> String {
952 "Software key".into()
953 }
954
955 fn sign(&self, digest: &[u8]) -> Result<Vec<Vec<u8>>, crate::Error> {
961 let signature = self.signing_key.sign(digest);
962 Ok(vec![signature.r_bytes().into(), signature.s_bytes().into()])
963 }
964
965 fn certificate(&self) -> Result<Option<Vec<u8>>, crate::Error> {
971 Ok(self.certificate.clone())
972 }
973
974 fn public(&self) -> Result<RawPublicKey, crate::Error> {
980 Ok(RawPublicKey::Ed25519(
981 self.signing_key.verifying_key().to_bytes().into(),
982 ))
983 }
984 }
985
986 #[test]
987 fn sign_dummy() -> TestResult {
988 let mut raw_signer = Ed25519SoftKey::new();
989
990 let cert = add_certificate(
991 &raw_signer,
992 Default::default(),
993 &[OpenPgpUserId::new("test".into())?],
994 Timestamp::now(),
995 Default::default(),
996 )?;
997
998 raw_signer.certificate = Some(cert);
999
1000 let mut data_to_sign = [0; 32];
1001 OsRng::fill_bytes(&mut OsRng, &mut data_to_sign);
1002
1003 let signature = sign(&raw_signer, &data_to_sign)?;
1004 assert!(!signature.is_empty());
1005
1006 Ok(())
1007 }
1008
1009 #[test]
1010 fn check_empty_user_ids() -> TestResult {
1011 use crate::signer::error::Error;
1012 use crate::signer::openpgp::SigningKey;
1013
1014 let mut raw_signer = Ed25519SoftKey::new();
1015
1016 let cert = add_certificate(
1018 &raw_signer,
1019 Default::default(),
1020 &[OpenPgpUserId::new("test".into())?],
1021 Timestamp::now(),
1022 Default::default(),
1023 )?;
1024
1025 let (cert, cert_fingerprint) = {
1027 let mut cert = SignedPublicKey::from_bytes(Cursor::new(cert))?;
1028 cert.details.users = vec![];
1029 (cert.to_bytes()?, cert.fingerprint())
1030 };
1031
1032 raw_signer.certificate = Some(cert);
1033
1034 assert_matches!(
1035 SigningKey::new_provisioned(&raw_signer),
1036 Err(crate::Error::Signer(Error::OpenPpgUserIdsMissing { fingerprint })) if fingerprint == cert_fingerprint
1037 );
1038
1039 Ok(())
1040 }
1041
1042 #[rstest::rstest]
1043 #[case::p256(ECCCurve::P256, KeyType::EcP256)]
1044 #[case::p384(ECCCurve::P384, KeyType::EcP384)]
1045 #[case::p521(ECCCurve::P521, KeyType::EcP521)]
1046 fn import_ecdsa(#[case] pgp_curve: ECCCurve, #[case] expected_type: KeyType) -> TestResult {
1047 let params = SecretKeyParamsBuilder::default()
1048 .key_type(ComposedKeyType::ECDSA(pgp_curve))
1049 .can_sign(true)
1050 .build()?;
1051
1052 let rng = OsRng;
1053
1054 let key = params.generate(rng)?;
1055 let actual_type = tsk_to_private_key_import(&key)?.0.key_type();
1056 assert_eq!(actual_type, expected_type);
1057
1058 Ok(())
1059 }
1060
1061 #[test]
1062 fn test_unsupported_ecdsa_curve() -> TestResult {
1063 let key = SecretKeyParamsBuilder::default()
1064 .key_type(ComposedKeyType::ECDSA(ECCCurve::Secp256k1))
1065 .can_sign(true)
1066 .build()?
1067 .generate(OsRng)?;
1068
1069 assert!(tsk_to_private_key_import(&key).is_err());
1070
1071 Ok(())
1072 }
1073}