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
68struct SigningKey<'a> {
73 public_key: PublicKey,
74 raw_signer: &'a dyn RawSigningKey,
75}
76
77impl std::fmt::Debug for SigningKey<'_> {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 f.debug_struct("SigningKey")
80 .field("public_key", &self.public_key)
81 .finish()
82 }
83}
84
85#[inline]
91fn to_rpgp_error(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> pgp::errors::Error {
92 pgp::errors::Error::IO {
93 source: std::io::Error::other(e),
94 backtrace: Some(Backtrace::capture()),
95 }
96}
97
98impl<'a> SigningKey<'a> {
99 fn new(raw_signer: &'a dyn RawSigningKey, public_key: PublicKey) -> Self {
101 Self {
102 raw_signer,
103 public_key,
104 }
105 }
106
107 fn new_provisioned(raw_signer: &'a dyn RawSigningKey) -> Result<Self, crate::Error> {
120 let public_key = if let Some(cert) = raw_signer.certificate()?.as_ref() {
121 SignedPublicKey::from_bytes(Cursor::new(cert))
122 .map_err(Error::Pgp)?
123 .primary_key
124 } else {
125 return Err(Error::OpenPpgCertificateMissing.into());
126 };
127 Ok(Self::new(raw_signer, public_key))
128 }
129}
130
131impl KeyDetails for SigningKey<'_> {
132 fn version(&self) -> KeyVersion {
133 self.public_key.version()
134 }
135
136 fn fingerprint(&self) -> Fingerprint {
137 self.public_key.fingerprint()
138 }
139
140 fn legacy_key_id(&self) -> KeyId {
141 self.public_key.legacy_key_id()
142 }
143
144 fn algorithm(&self) -> PublicKeyAlgorithm {
145 self.public_key.algorithm()
146 }
147
148 fn created_at(&self) -> Timestamp {
149 self.public_key.created_at()
150 }
151
152 fn legacy_v3_expiration_days(&self) -> Option<u16> {
153 self.public_key.legacy_v3_expiration_days()
154 }
155
156 fn public_params(&self) -> &PublicParams {
157 self.public_key.public_params()
158 }
159}
160
161impl RpgpSigningKey for SigningKey<'_> {
162 fn sign(
180 &self,
181 _key_pw: &Password,
182 hash: HashAlgorithm,
183 data: &[u8],
184 ) -> pgp::errors::Result<SignatureBytes> {
185 if hash != self.hash_alg() {
186 error!(
187 "Requested signing hash is different from the default supported, got {hash} expected {expected}",
188 expected = self.hash_alg()
189 );
190 return Err(to_rpgp_error(Error::UnsupportedHashAlgorithm {
191 actual: hash,
192 expected: self.hash_alg(),
193 }));
194 }
195 let sig = self.raw_signer.sign(data).map_err(|e| {
196 error!("RawSigner::sign failed: {e:?}");
197 to_rpgp_error(e)
198 })?;
199
200 Ok(SignatureBytes::Mpis(
201 sig.into_iter().map(|b| Mpi::from_slice(&b)).collect(),
202 ))
203 }
204
205 fn hash_alg(&self) -> HashAlgorithm {
211 HashAlgorithm::Sha512
212 }
213}
214
215pub fn add_certificate(
228 raw_signer: &dyn RawSigningKey,
229 flags: OpenPgpKeyUsageFlags,
230 user_ids: &[OpenPgpUserId],
231 created_at: Timestamp,
232 version: OpenPgpVersion,
233) -> Result<Vec<u8>, crate::Error> {
234 if version != OpenPgpVersion::V4 {
235 return Err(crate::openpgp::Error::InvalidOpenPgpVersion(version.to_string()).into());
236 }
237
238 if user_ids.is_empty() {
239 return Err(crate::openpgp::Error::OpenPgpUserIdMissing.into());
240 }
241
242 let (primary_user_id, user_ids) = {
243 let mut user_ids = user_ids
244 .iter()
245 .map(|user_id| UserId::from_str(Default::default(), user_id))
246 .collect::<Result<Vec<UserId>, _>>()
247 .map_err(Error::Pgp)?;
248
249 (user_ids.remove(0), user_ids)
250 };
251
252 let public_key = raw_signer.public()?.to_openpgp_public_key(created_at)?;
253 let signer = SigningKey::new(raw_signer, public_key.clone());
254
255 let signed_pk = SignedPublicKey {
256 details: ComposedKeyDetails::new(
257 Some(primary_user_id),
258 user_ids,
259 vec![],
260 flags.into(),
261 Default::default(),
262 Default::default(),
263 Default::default(),
264 vec![CompressionAlgorithm::Uncompressed].into(),
265 vec![].into(),
266 )
267 .sign(thread_rng(), &signer, &public_key, &Password::empty())
268 .map_err(Error::Pgp)?,
269 primary_key: public_key,
270 public_subkeys: vec![],
271 };
272
273 let mut buffer = vec![];
274 signed_pk.to_writer(&mut buffer).map_err(Error::Pgp)?;
275 Ok(buffer)
276}
277
278pub fn tsk_to_private_key_import(
288 key: &SignedSecretKey,
289) -> Result<(PrivateKeyImport, KeyMechanism), crate::Error> {
290 if !key.secret_subkeys.is_empty() {
291 return Err(Error::OpenPgpTskContainsMultipleComponentKeys {
292 fingerprint: key.fingerprint(),
293 }
294 .into());
295 }
296 let SecretParams::Plain(secret) = key.primary_key.secret_params() else {
297 return Err(Error::OpenPgpTskIsPassphraseProtected {
298 fingerprint: key.fingerprint(),
299 }
300 .into());
301 };
302 Ok(match (secret, key.public_key().public_params()) {
303 (PlainSecretParams::RSA(secret), PublicParams::RSA(public)) => {
304 key_type_matches_length(
306 KeyType::Rsa,
307 Some(public.key.n().to_bytes_be().len() as u32 * 8),
308 )?;
309
310 let (_d, p, q, _u) = secret.to_bytes();
311
312 (
313 PrivateKeyImport::from_rsa(p, q, public.key.e().to_bytes_be().to_vec()),
314 KeyMechanism::RsaSignaturePkcs1,
315 )
316 }
317 (PlainSecretParams::ECDSA(secret_key), _) => {
318 let ec = if let PublicParams::ECDSA(pp) = key.primary_key.public_key().public_params() {
319 match pp {
320 EcdsaPublicParams::P256 { .. } => KeyType::EcP256,
321 EcdsaPublicParams::P384 { .. } => KeyType::EcP384,
322 EcdsaPublicParams::P521 { .. } => KeyType::EcP521,
323 pp => {
324 warn!("Unsupported ECDSA parameters: {pp:?}");
325 return Err(Error::UnsupportedKeyFormat {
326 context: "converting ECDSA key to private key import",
327 public_params: Box::new(key.public_key().public_params().clone()),
328 })?;
329 }
330 }
331 } else {
332 return Err(Error::UnsupportedKeyFormat {
333 context: "converting non-ECDSA key to private key import",
334 public_params: Box::new(key.public_key().public_params().clone()),
335 }
336 .into());
337 };
338
339 let bytes = match secret_key {
340 SecretKey::P256(secret_key) => secret_key.to_bytes().to_vec(),
341 SecretKey::P384(secret_key) => secret_key.to_bytes().to_vec(),
342 SecretKey::P521(secret_key) => secret_key.to_bytes().to_vec(),
343 SecretKey::Secp256k1(secret_key) => secret_key.to_bytes().to_vec(),
344 secret_key => {
345 warn!("Unsupported secret key parameters: {secret_key:?}");
346 return Err(Error::UnsupportedKeyFormat {
347 context: "converting unsupported ECDSA key to private key import",
348 public_params: Box::new(key.public_key().public_params().clone()),
349 })?;
350 }
351 };
352
353 (
354 PrivateKeyImport::from_raw_bytes(ec, bytes)?,
355 KeyMechanism::EcdsaSignature,
356 )
357 }
358 (PlainSecretParams::EdDSALegacy(EdDsaLegacySecretKey::Ed25519(bytes)), _) => (
359 PrivateKeyImport::from_raw_bytes(KeyType::Curve25519, bytes.as_bytes())?,
360 KeyMechanism::EdDsaSignature,
361 ),
362 (_, public_params) => {
363 return Err(Error::UnsupportedKeyFormat {
364 context: "converting unknown key format to private key import",
365 public_params: Box::new(public_params.clone()),
366 }
367 .into());
368 }
369 })
370}
371
372pub fn sign(raw_signer: &dyn RawSigningKey, message: &[u8]) -> Result<Vec<u8>, crate::Error> {
391 let signer = SigningKey::new_provisioned(raw_signer)?;
392
393 let mut sig_config =
394 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
395 sig_config.hashed_subpackets = vec![
396 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
397 .map_err(Error::Pgp)?,
398 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
399 .map_err(Error::Pgp)?,
400 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
401 .map_err(Error::Pgp)?,
402 ];
403
404 let mut hasher = sig_config
405 .hash_alg
406 .new_hasher()
407 .map_err(|source| Error::Pgp(to_rpgp_error(source)))?;
408 sig_config
409 .hash_data_to_sign(&mut hasher, message)
410 .map_err(Error::Pgp)?;
411
412 let len = sig_config
413 .hash_signature_data(&mut hasher)
414 .map_err(Error::Pgp)?;
415
416 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
417
418 let hash = &hasher.finalize()[..];
419
420 let signed_hash_value = [hash[0], hash[1]];
421 let raw_sig = signer
422 .sign(&Password::empty(), sig_config.hash_alg, hash)
423 .map_err(Error::Pgp)?;
424
425 let signature =
426 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
427
428 let mut out = vec![];
429 signature
430 .to_writer_with_header(&mut out)
431 .map_err(Error::Pgp)?;
432
433 Ok(out)
434}
435
436#[derive(Clone, Default)]
446struct Hasher(sha2::Sha512);
447
448impl DynDigest for Hasher {
449 fn update(&mut self, data: &[u8]) {
453 self.0.update(data);
454 }
455
456 fn finalize_into(self, buf: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
462 sha2::digest::DynDigest::finalize_into(self.0, buf)
463 .map_err(|_| digest::InvalidBufferSize)?;
464 Ok(())
465 }
466
467 fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
473 sha2::digest::DynDigest::finalize_into_reset(&mut self.0, out)
474 .map_err(|_| digest::InvalidBufferSize)?;
475 Ok(())
476 }
477
478 fn reset(&mut self) {
480 sha2::digest::DynDigest::reset(&mut self.0)
481 }
482
483 fn output_size(&self) -> usize {
485 sha2::digest::DynDigest::output_size(&self.0)
486 }
487
488 fn box_clone(&self) -> Box<dyn DynDigest> {
490 Box::new(self.clone())
491 }
492}
493
494pub fn sign_hasher_state(
513 raw_signer: &dyn RawSigningKey,
514 state: sha2::Sha512,
515) -> Result<String, crate::Error> {
516 let signer = SigningKey::new_provisioned(raw_signer)?;
517 let hasher = state.clone();
518
519 let file_hash = Box::new(hasher).finalize().to_vec();
520
521 let sig_config = {
522 let mut sig_config =
523 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
524 sig_config.hashed_subpackets = vec![
525 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
526 .map_err(Error::Pgp)?,
527 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
528 .map_err(Error::Pgp)?,
529 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
530 .map_err(Error::Pgp)?,
531 Subpacket::regular(SubpacketData::Notation(Notation {
532 readable: false,
533 name: "data-digest@archlinux.org".into(),
534 value: file_hash.into(),
535 }))
536 .map_err(Error::Pgp)?,
537 ];
538 sig_config
539 };
540
541 let mut hasher = Box::new(Hasher(state.clone())) as Box<dyn DynDigest + Send>;
542
543 let len = sig_config
544 .hash_signature_data(&mut hasher)
545 .map_err(Error::Pgp)?;
546
547 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
548
549 let hash = &hasher.finalize()[..];
550
551 let signed_hash_value = [hash[0], hash[1]];
552
553 let raw_sig = signer
554 .sign(&Password::empty(), sig_config.hash_alg, hash)
555 .map_err(Error::Pgp)?;
556
557 let signature =
558 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
559
560 let signature = DetachedSignature { signature };
561 Ok(signature
562 .to_armored_string(ArmorOptions::default())
563 .map_err(Error::Pgp)?)
564}
565
566fn ecdsa_to_public_key(created_at: Timestamp, key: EcdsaPublicParams) -> Result<PublicKey, Error> {
577 Ok(PublicKey::from_inner(PubKeyInner::new(
578 KeyVersion::V4,
579 PublicKeyAlgorithm::ECDSA,
580 created_at,
581 None,
582 PublicParams::ECDSA(key),
583 )?)?)
584}
585
586impl RawPublicKey {
587 fn to_openpgp_public_key(&self, created_at: Timestamp) -> Result<PublicKey, Error> {
603 Ok(match self {
604 RawPublicKey::Rsa { modulus, exponent } => PublicKey::from_inner(PubKeyInner::new(
605 KeyVersion::V4,
606 PublicKeyAlgorithm::RSA,
607 created_at,
608 None,
609 PublicParams::RSA(RsaPublicParams {
610 key: RsaPublicKey::new(
611 BigUint::from_bytes_be(modulus),
612 BigUint::from_bytes_be(exponent),
613 )
614 .map_err(to_rpgp_error)?,
615 }),
616 )?)?,
617
618 RawPublicKey::Ed25519(pubkey) => PublicKey::from_inner(PubKeyInner::new(
619 KeyVersion::V4,
620 PublicKeyAlgorithm::EdDSALegacy,
621 created_at,
622 None,
623 PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 {
624 key: VerifyingKey::from_bytes(&pubkey[..].try_into().map_err(to_rpgp_error)?)
625 .map_err(to_rpgp_error)?,
626 }),
627 )?)?,
628
629 RawPublicKey::P256(pubkey) => ecdsa_to_public_key(
630 created_at,
631 EcdsaPublicParams::P256 {
632 key: p256::PublicKey::from_sec1_bytes(pubkey)?,
633 },
634 )?,
635
636 RawPublicKey::P384(pubkey) => ecdsa_to_public_key(
637 created_at,
638 EcdsaPublicParams::P384 {
639 key: p384::PublicKey::from_sec1_bytes(pubkey)?,
640 },
641 )?,
642
643 RawPublicKey::P521(pubkey) => ecdsa_to_public_key(
644 created_at,
645 EcdsaPublicParams::P521 {
646 key: p521::PublicKey::from_sec1_bytes(pubkey)?,
647 },
648 )?,
649 })
650 }
651}
652
653pub fn extract_certificate(key: SignedSecretKey) -> Result<Vec<u8>, crate::Error> {
666 let public: SignedPublicKey = key.into();
667 let mut buffer = vec![];
668 public.to_writer(&mut buffer).map_err(Error::Pgp)?;
669 Ok(buffer)
670}
671
672#[cfg(test)]
673mod tests {
674 use ed25519_dalek::{Signer, SigningKey};
675 use pgp::{
676 composed::{KeyType as ComposedKeyType, SecretKeyParamsBuilder},
677 crypto::ecc_curve::ECCCurve,
678 types::{EcdsaPublicParams, PublicParams},
679 };
680 use rand::RngCore;
681 use rsa::rand_core::OsRng;
682 use testresult::TestResult;
683
684 use super::*;
685
686 #[test]
687 fn convert_ed25519_to_pgp() -> TestResult {
688 let hsm_key = RawPublicKey::Ed25519(vec![
689 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29, 198,
690 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10,
691 ]);
692
693 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
694 let PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 { key }) =
695 pgp_key.public_params()
696 else {
697 panic!("Wrong type of public params");
698 };
699 assert_eq!(
700 key.to_bytes(),
701 [
702 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29,
703 198, 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10
704 ]
705 );
706
707 Ok(())
708 }
709
710 #[test]
711 fn convert_p256_to_pgp() -> TestResult {
712 let hsm_key = RawPublicKey::P256(vec![
713 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130, 169,
714 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240, 240, 134,
715 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122, 89, 2, 180, 2,
716 237, 15, 248, 104, 83, 142, 22, 185, 133,
717 ]);
718 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
719 let PublicParams::ECDSA(EcdsaPublicParams::P256 { key, .. }) = pgp_key.public_params()
720 else {
721 panic!("Wrong type of public params");
722 };
723 assert_eq!(
724 key.to_sec1_bytes().to_vec(),
725 [
726 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130,
727 169, 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240,
728 240, 134, 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122,
729 89, 2, 180, 2, 237, 15, 248, 104, 83, 142, 22, 185, 133
730 ]
731 );
732
733 Ok(())
734 }
735
736 #[test]
737 fn convert_p384_to_pgp() -> TestResult {
738 let hsm_key = RawPublicKey::P384(vec![
739 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72, 250,
740 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8, 66, 117,
741 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8, 75, 151, 252,
742 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82, 134, 134, 6, 17,
743 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139, 217, 90, 220, 239, 191,
744 148,
745 ]);
746 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
747 let PublicParams::ECDSA(EcdsaPublicParams::P384 { 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, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72,
755 250, 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8,
756 66, 117, 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8,
757 75, 151, 252, 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82,
758 134, 134, 6, 17, 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139,
759 217, 90, 220, 239, 191, 148
760 ]
761 );
762
763 Ok(())
764 }
765
766 #[test]
767 fn convert_p521_to_pgp() -> TestResult {
768 let hsm_key = RawPublicKey::P521(vec![
769 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211, 118,
770 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96, 102, 55,
771 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26, 190, 40, 157,
772 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243, 67, 14, 159, 46,
773 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76, 198, 240, 32, 108, 48,
774 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10, 65, 118, 233, 79, 179, 90,
775 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102, 113, 26, 103, 127, 234, 47, 81,
776 ]);
777 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
778 let PublicParams::ECDSA(EcdsaPublicParams::P521 { key, .. }) = pgp_key.public_params()
779 else {
780 panic!("Wrong type of public params");
781 };
782 assert_eq!(
783 key.to_sec1_bytes().to_vec(),
784 [
785 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211,
786 118, 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96,
787 102, 55, 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26,
788 190, 40, 157, 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243,
789 67, 14, 159, 46, 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76,
790 198, 240, 32, 108, 48, 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10,
791 65, 118, 233, 79, 179, 90, 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102,
792 113, 26, 103, 127, 234, 47, 81
793 ]
794 );
795
796 Ok(())
797 }
798
799 #[test]
800 fn convert_rsa_to_pgp() -> TestResult {
801 let hsm_key = RawPublicKey::Rsa {
802 modulus: vec![
803 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
804 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
805 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
806 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
807 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
808 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
809 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
810 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
811 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
812 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
813 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
814 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
815 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
816 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
817 59, 161, 187,
818 ],
819 exponent: vec![1, 0, 1],
820 };
821 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
822 let PublicParams::RSA(public) = pgp_key.public_params() else {
823 panic!("Wrong type of public params");
824 };
825 assert_eq!(public.key.e().to_bytes_be(), [1, 0, 1]);
826 assert_eq!(
827 public.key.n().to_bytes_be(),
828 [
829 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
830 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
831 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
832 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
833 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
834 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
835 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
836 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
837 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
838 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
839 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
840 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
841 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
842 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
843 59, 161, 187
844 ]
845 );
846
847 Ok(())
848 }
849
850 #[cfg(feature = "nethsm")]
852 mod nethsm {
853 use std::fs::File;
854
855 use base64ct::{Base64, Encoding as _};
856 use nethsm_sdk_rs::models::KeyPrivateData;
857
858 use super::*;
859
860 #[test]
861 fn private_key_import_ed25199_is_correctly_zero_padded() -> TestResult {
862 let key = SignedSecretKey::from_armor_single(File::open(
863 "tests/fixtures/ed25519-key-with-31-byte-private-key-scalar.asc",
864 )?)?
865 .0;
866
867 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
868
869 let data = Base64::decode_vec(&import.data.unwrap())?;
870
871 assert_eq!(data.len(), 32);
874 assert_eq!(data[0], 0x00);
875
876 Ok(())
877 }
878
879 #[test]
880 #[cfg(feature = "nethsm")]
881 fn private_key_import_rsa_key_with_nonstandard_moduli_is_read_correctly() -> TestResult {
882 let key = SignedSecretKey::from_armor_single(File::open(
883 "tests/fixtures/rsa-key-with-modulus-e-257.asc",
884 )?)?
885 .0;
886
887 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
888
889 let data = Base64::decode_vec(&import.public_exponent.unwrap())?;
890
891 assert_eq!(data, vec![0x01, 0x01]); Ok(())
895 }
896 }
897
898 struct Ed25519SoftKey {
900 signing_key: SigningKey,
902
903 certificate: Option<Vec<u8>>,
905 }
906
907 impl Ed25519SoftKey {
908 fn new() -> Self {
912 Self {
913 signing_key: SigningKey::generate(&mut OsRng),
916 certificate: None,
917 }
918 }
919 }
920
921 impl RawSigningKey for Ed25519SoftKey {
922 fn key_id(&self) -> String {
924 "Software key".into()
925 }
926
927 fn sign(&self, digest: &[u8]) -> Result<Vec<Vec<u8>>, crate::Error> {
933 let signature = self.signing_key.sign(digest);
934 Ok(vec![signature.r_bytes().into(), signature.s_bytes().into()])
935 }
936
937 fn certificate(&self) -> Result<Option<Vec<u8>>, crate::Error> {
943 Ok(self.certificate.clone())
944 }
945
946 fn public(&self) -> Result<RawPublicKey, crate::Error> {
952 Ok(RawPublicKey::Ed25519(
953 self.signing_key.verifying_key().to_bytes().into(),
954 ))
955 }
956 }
957
958 #[test]
959 fn sign_dummy() -> TestResult {
960 let mut raw_signer = Ed25519SoftKey::new();
961
962 let cert = add_certificate(
963 &raw_signer,
964 Default::default(),
965 &[OpenPgpUserId::new("test".into())?],
966 Timestamp::now(),
967 Default::default(),
968 )?;
969
970 raw_signer.certificate = Some(cert);
971
972 let mut data_to_sign = [0; 32];
973 OsRng::fill_bytes(&mut OsRng, &mut data_to_sign);
974
975 let signature = sign(&raw_signer, &data_to_sign)?;
976 assert!(!signature.is_empty());
977
978 Ok(())
979 }
980
981 #[rstest::rstest]
982 #[case::p256(ECCCurve::P256, KeyType::EcP256)]
983 #[case::p384(ECCCurve::P384, KeyType::EcP384)]
984 #[case::p521(ECCCurve::P521, KeyType::EcP521)]
985 fn import_ecdsa(#[case] pgp_curve: ECCCurve, #[case] expected_type: KeyType) -> TestResult {
986 let params = SecretKeyParamsBuilder::default()
987 .key_type(ComposedKeyType::ECDSA(pgp_curve))
988 .can_sign(true)
989 .build()?;
990
991 let rng = OsRng;
992
993 let key = params.generate(rng)?;
994 let actual_type = tsk_to_private_key_import(&key)?.0.key_type();
995 assert_eq!(actual_type, expected_type);
996
997 Ok(())
998 }
999
1000 #[test]
1001 fn test_unsupported_ecdsa_curve() -> TestResult {
1002 let key = SecretKeyParamsBuilder::default()
1003 .key_type(ComposedKeyType::ECDSA(ECCCurve::Secp256k1))
1004 .can_sign(true)
1005 .build()?
1006 .generate(OsRng)?;
1007
1008 assert!(tsk_to_private_key_import(&key).is_err());
1009
1010 Ok(())
1011 }
1012}