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::{ecdsa::SecretKey, hash::HashAlgorithm, public_key::PublicKeyAlgorithm},
19 packet::{
20 Notation,
21 PacketTrait,
22 PubKeyInner,
23 PublicKey,
24 Signature,
25 SignatureConfig,
26 SignatureType,
27 Subpacket,
28 SubpacketData,
29 UserId,
30 },
31 ser::Serialize,
32 types::{
33 CompressionAlgorithm,
34 EcdsaPublicParams,
35 EddsaLegacyPublicParams,
36 Fingerprint,
37 KeyDetails,
38 KeyId,
39 KeyVersion,
40 Mpi,
41 Password,
42 PlainSecretParams,
43 PublicParams,
44 RsaPublicParams,
45 SecretParams,
46 SignatureBytes,
47 SigningKey as RpgpSigningKey,
48 },
49};
50use rand::thread_rng;
51use rsa::{BigUint, RsaPublicKey, traits::PublicKeyParts as _};
52use sha2::digest::Digest as _;
53
54use crate::{
55 key::{KeyMechanism, KeyType, PrivateKeyImport, key_type_matches_length},
56 openpgp::{OpenPgpKeyUsageFlags, OpenPgpUserId, OpenPgpVersion},
57 signer::{
58 error::Error,
59 traits::{RawPublicKey, RawSigningKey},
60 },
61};
62
63struct SigningKey<'a> {
68 public_key: PublicKey,
69 raw_signer: &'a dyn RawSigningKey,
70}
71
72impl std::fmt::Debug for SigningKey<'_> {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 f.debug_struct("SigningKey")
75 .field("public_key", &self.public_key)
76 .finish()
77 }
78}
79
80#[inline]
86fn to_rpgp_error(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> pgp::errors::Error {
87 pgp::errors::Error::IO {
88 source: std::io::Error::other(e),
89 backtrace: Some(Backtrace::capture()),
90 }
91}
92
93impl<'a> SigningKey<'a> {
94 fn new(raw_signer: &'a dyn RawSigningKey, public_key: PublicKey) -> Self {
96 Self {
97 raw_signer,
98 public_key,
99 }
100 }
101
102 fn new_provisioned(raw_signer: &'a dyn RawSigningKey) -> Result<Self, crate::Error> {
115 let public_key = if let Some(cert) = raw_signer.certificate()?.as_ref() {
116 SignedPublicKey::from_bytes(Cursor::new(cert))
117 .map_err(Error::Pgp)?
118 .primary_key
119 } else {
120 return Err(Error::OpenPpgCertificateMissing.into());
121 };
122 Ok(Self::new(raw_signer, public_key))
123 }
124}
125
126impl KeyDetails for SigningKey<'_> {
127 fn version(&self) -> KeyVersion {
128 self.public_key.version()
129 }
130
131 fn fingerprint(&self) -> Fingerprint {
132 self.public_key.fingerprint()
133 }
134
135 fn legacy_key_id(&self) -> KeyId {
136 self.public_key.legacy_key_id()
137 }
138
139 fn algorithm(&self) -> PublicKeyAlgorithm {
140 self.public_key.algorithm()
141 }
142
143 fn created_at(&self) -> Timestamp {
144 self.public_key.created_at()
145 }
146
147 fn legacy_v3_expiration_days(&self) -> Option<u16> {
148 self.public_key.legacy_v3_expiration_days()
149 }
150
151 fn public_params(&self) -> &PublicParams {
152 self.public_key.public_params()
153 }
154}
155
156impl RpgpSigningKey for SigningKey<'_> {
157 fn sign(
175 &self,
176 _key_pw: &Password,
177 hash: HashAlgorithm,
178 data: &[u8],
179 ) -> pgp::errors::Result<SignatureBytes> {
180 if hash != self.hash_alg() {
181 error!(
182 "Requested signing hash is different from the default supported, got {hash} expected {expected}",
183 expected = self.hash_alg()
184 );
185 return Err(to_rpgp_error(Error::UnsupportedHashAlgorithm {
186 actual: hash,
187 expected: self.hash_alg(),
188 }));
189 }
190 let sig = self.raw_signer.sign(data).map_err(|e| {
191 error!("RawSigner::sign failed: {e:?}");
192 to_rpgp_error(e)
193 })?;
194
195 Ok(SignatureBytes::Mpis(
196 sig.into_iter().map(|b| Mpi::from_slice(&b)).collect(),
197 ))
198 }
199
200 fn hash_alg(&self) -> HashAlgorithm {
206 HashAlgorithm::Sha512
207 }
208}
209
210pub fn add_certificate(
220 raw_signer: &dyn RawSigningKey,
221 flags: OpenPgpKeyUsageFlags,
222 user_id: OpenPgpUserId,
223 created_at: Timestamp,
224 version: OpenPgpVersion,
225) -> Result<Vec<u8>, crate::Error> {
226 if version != OpenPgpVersion::V4 {
227 return Err(crate::openpgp::Error::InvalidOpenPgpVersion(version.to_string()).into());
228 }
229 let public_key = raw_signer.public()?.to_openpgp_public_key(created_at)?;
230 let signer = SigningKey::new(raw_signer, public_key.clone());
231
232 let signed_pk = SignedPublicKey {
233 details: ComposedKeyDetails::new(
234 Some(UserId::from_str(Default::default(), user_id.as_ref()).map_err(Error::Pgp)?),
235 vec![],
236 vec![],
237 flags.into(),
238 Default::default(),
239 Default::default(),
240 Default::default(),
241 vec![CompressionAlgorithm::Uncompressed].into(),
242 vec![].into(),
243 )
244 .sign(thread_rng(), &signer, &public_key, &Password::empty())
245 .map_err(Error::Pgp)?,
246 primary_key: public_key,
247 public_subkeys: vec![],
248 };
249
250 let mut buffer = vec![];
251 signed_pk.to_writer(&mut buffer).map_err(Error::Pgp)?;
252 Ok(buffer)
253}
254
255pub fn tsk_to_private_key_import(
265 key: &SignedSecretKey,
266) -> Result<(PrivateKeyImport, KeyMechanism), crate::Error> {
267 if !key.secret_subkeys.is_empty() {
268 return Err(Error::OpenPgpTskContainsMultipleComponentKeys {
269 fingerprint: key.fingerprint(),
270 }
271 .into());
272 }
273 let SecretParams::Plain(secret) = key.primary_key.secret_params() else {
274 return Err(Error::OpenPgpTskIsPassphraseProtected {
275 fingerprint: key.fingerprint(),
276 }
277 .into());
278 };
279 Ok(match (secret, key.public_key().public_params()) {
280 (PlainSecretParams::RSA(secret), PublicParams::RSA(public)) => {
281 key_type_matches_length(
283 KeyType::Rsa,
284 Some(public.key.n().to_bytes_be().len() as u32 * 8),
285 )?;
286
287 let (_d, p, q, _u) = secret.to_bytes();
288
289 (
290 PrivateKeyImport::from_rsa(p, q, public.key.e().to_bytes_be().to_vec()),
291 KeyMechanism::RsaSignaturePkcs1,
292 )
293 }
294 (PlainSecretParams::ECDSA(secret_key), _) => {
295 let ec = if let PublicParams::ECDSA(pp) = key.primary_key.public_key().public_params() {
296 match pp {
297 EcdsaPublicParams::P256 { .. } => KeyType::EcP256,
298 EcdsaPublicParams::P384 { .. } => KeyType::EcP384,
299 EcdsaPublicParams::P521 { .. } => KeyType::EcP521,
300 pp => {
301 warn!("Unsupported ECDSA parameters: {pp:?}");
302 return Err(Error::UnsupportedKeyFormat {
303 context: "converting ECDSA key to private key import",
304 public_params: Box::new(key.public_key().public_params().clone()),
305 })?;
306 }
307 }
308 } else {
309 return Err(Error::UnsupportedKeyFormat {
310 context: "converting non-ECDSA key to private key import",
311 public_params: Box::new(key.public_key().public_params().clone()),
312 }
313 .into());
314 };
315
316 let bytes = match secret_key {
317 SecretKey::P256(secret_key) => secret_key.to_bytes().to_vec(),
318 SecretKey::P384(secret_key) => secret_key.to_bytes().to_vec(),
319 SecretKey::P521(secret_key) => secret_key.to_bytes().to_vec(),
320 SecretKey::Secp256k1(secret_key) => secret_key.to_bytes().to_vec(),
321 secret_key => {
322 warn!("Unsupported secret key parameters: {secret_key:?}");
323 return Err(Error::UnsupportedKeyFormat {
324 context: "converting unsupported ECDSA key to private key import",
325 public_params: Box::new(key.public_key().public_params().clone()),
326 })?;
327 }
328 };
329
330 (
331 PrivateKeyImport::from_raw_bytes(ec, bytes)?,
332 KeyMechanism::EcdsaSignature,
333 )
334 }
335 (PlainSecretParams::Ed25519Legacy(bytes), _) => (
336 PrivateKeyImport::from_raw_bytes(KeyType::Curve25519, bytes.as_bytes())?,
337 KeyMechanism::EdDsaSignature,
338 ),
339 (_, public_params) => {
340 return Err(Error::UnsupportedKeyFormat {
341 context: "converting unknown key format to private key import",
342 public_params: Box::new(public_params.clone()),
343 }
344 .into());
345 }
346 })
347}
348
349pub fn sign(raw_signer: &dyn RawSigningKey, message: &[u8]) -> Result<Vec<u8>, crate::Error> {
368 let signer = SigningKey::new_provisioned(raw_signer)?;
369
370 let mut sig_config =
371 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
372 sig_config.hashed_subpackets = vec![
373 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
374 .map_err(Error::Pgp)?,
375 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
376 .map_err(Error::Pgp)?,
377 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
378 .map_err(Error::Pgp)?,
379 ];
380
381 let mut hasher = sig_config
382 .hash_alg
383 .new_hasher()
384 .map_err(|source| Error::Pgp(to_rpgp_error(source)))?;
385 sig_config
386 .hash_data_to_sign(&mut hasher, message)
387 .map_err(Error::Pgp)?;
388
389 let len = sig_config
390 .hash_signature_data(&mut hasher)
391 .map_err(Error::Pgp)?;
392
393 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
394
395 let hash = &hasher.finalize()[..];
396
397 let signed_hash_value = [hash[0], hash[1]];
398 let raw_sig = signer
399 .sign(&Password::empty(), sig_config.hash_alg, hash)
400 .map_err(Error::Pgp)?;
401
402 let signature =
403 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
404
405 let mut out = vec![];
406 signature
407 .to_writer_with_header(&mut out)
408 .map_err(Error::Pgp)?;
409
410 Ok(out)
411}
412
413#[derive(Clone, Default)]
423struct Hasher(sha2::Sha512);
424
425impl DynDigest for Hasher {
426 fn update(&mut self, data: &[u8]) {
430 self.0.update(data);
431 }
432
433 fn finalize_into(self, buf: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
439 sha2::digest::DynDigest::finalize_into(self.0, buf)
440 .map_err(|_| digest::InvalidBufferSize)?;
441 Ok(())
442 }
443
444 fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
450 sha2::digest::DynDigest::finalize_into_reset(&mut self.0, out)
451 .map_err(|_| digest::InvalidBufferSize)?;
452 Ok(())
453 }
454
455 fn reset(&mut self) {
457 sha2::digest::DynDigest::reset(&mut self.0)
458 }
459
460 fn output_size(&self) -> usize {
462 sha2::digest::DynDigest::output_size(&self.0)
463 }
464
465 fn box_clone(&self) -> Box<dyn DynDigest> {
467 Box::new(self.clone())
468 }
469}
470
471pub fn sign_hasher_state(
490 raw_signer: &dyn RawSigningKey,
491 state: sha2::Sha512,
492) -> Result<String, crate::Error> {
493 let signer = SigningKey::new_provisioned(raw_signer)?;
494 let hasher = state.clone();
495
496 let file_hash = Box::new(hasher).finalize().to_vec();
497
498 let sig_config = {
499 let mut sig_config =
500 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
501 sig_config.hashed_subpackets = vec![
502 Subpacket::regular(SubpacketData::SignatureCreationTime(Timestamp::now()))
503 .map_err(Error::Pgp)?,
504 Subpacket::regular(SubpacketData::IssuerKeyId(signer.legacy_key_id()))
505 .map_err(Error::Pgp)?,
506 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))
507 .map_err(Error::Pgp)?,
508 Subpacket::regular(SubpacketData::Notation(Notation {
509 readable: false,
510 name: "data-digest@archlinux.org".into(),
511 value: file_hash.into(),
512 }))
513 .map_err(Error::Pgp)?,
514 ];
515 sig_config
516 };
517
518 let mut hasher = Box::new(Hasher(state.clone())) as Box<dyn DynDigest + Send>;
519
520 let len = sig_config
521 .hash_signature_data(&mut hasher)
522 .map_err(Error::Pgp)?;
523
524 hasher.update(&sig_config.trailer(len).map_err(Error::Pgp)?);
525
526 let hash = &hasher.finalize()[..];
527
528 let signed_hash_value = [hash[0], hash[1]];
529
530 let raw_sig = signer
531 .sign(&Password::empty(), sig_config.hash_alg, hash)
532 .map_err(Error::Pgp)?;
533
534 let signature =
535 Signature::from_config(sig_config, signed_hash_value, raw_sig).map_err(Error::Pgp)?;
536
537 let signature = DetachedSignature { signature };
538 Ok(signature
539 .to_armored_string(ArmorOptions::default())
540 .map_err(Error::Pgp)?)
541}
542
543fn ecdsa_to_public_key(created_at: Timestamp, key: EcdsaPublicParams) -> Result<PublicKey, Error> {
554 Ok(PublicKey::from_inner(PubKeyInner::new(
555 KeyVersion::V4,
556 PublicKeyAlgorithm::ECDSA,
557 created_at,
558 None,
559 PublicParams::ECDSA(key),
560 )?)?)
561}
562
563impl RawPublicKey {
564 fn to_openpgp_public_key(&self, created_at: Timestamp) -> Result<PublicKey, Error> {
580 Ok(match self {
581 RawPublicKey::Rsa { modulus, exponent } => PublicKey::from_inner(PubKeyInner::new(
582 KeyVersion::V4,
583 PublicKeyAlgorithm::RSA,
584 created_at,
585 None,
586 PublicParams::RSA(RsaPublicParams {
587 key: RsaPublicKey::new(
588 BigUint::from_bytes_be(modulus),
589 BigUint::from_bytes_be(exponent),
590 )
591 .map_err(to_rpgp_error)?,
592 }),
593 )?)?,
594
595 RawPublicKey::Ed25519(pubkey) => PublicKey::from_inner(PubKeyInner::new(
596 KeyVersion::V4,
597 PublicKeyAlgorithm::EdDSALegacy,
598 created_at,
599 None,
600 PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 {
601 key: VerifyingKey::from_bytes(&pubkey[..].try_into().map_err(to_rpgp_error)?)
602 .map_err(to_rpgp_error)?,
603 }),
604 )?)?,
605
606 RawPublicKey::P256(pubkey) => ecdsa_to_public_key(
607 created_at,
608 EcdsaPublicParams::P256 {
609 key: p256::PublicKey::from_sec1_bytes(pubkey)?,
610 },
611 )?,
612
613 RawPublicKey::P384(pubkey) => ecdsa_to_public_key(
614 created_at,
615 EcdsaPublicParams::P384 {
616 key: p384::PublicKey::from_sec1_bytes(pubkey)?,
617 },
618 )?,
619
620 RawPublicKey::P521(pubkey) => ecdsa_to_public_key(
621 created_at,
622 EcdsaPublicParams::P521 {
623 key: p521::PublicKey::from_sec1_bytes(pubkey)?,
624 },
625 )?,
626 })
627 }
628}
629
630pub fn extract_certificate(key: SignedSecretKey) -> Result<Vec<u8>, crate::Error> {
643 let public: SignedPublicKey = key.into();
644 let mut buffer = vec![];
645 public.to_writer(&mut buffer).map_err(Error::Pgp)?;
646 Ok(buffer)
647}
648
649#[cfg(test)]
650mod tests {
651 use ed25519_dalek::{Signer, SigningKey};
652 use pgp::{
653 composed::{KeyType as ComposedKeyType, SecretKeyParamsBuilder},
654 crypto::ecc_curve::ECCCurve,
655 types::{EcdsaPublicParams, PublicParams},
656 };
657 use rand::RngCore;
658 use rsa::rand_core::OsRng;
659 use testresult::TestResult;
660
661 use super::*;
662
663 #[test]
664 fn convert_ed25519_to_pgp() -> TestResult {
665 let hsm_key = RawPublicKey::Ed25519(vec![
666 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29, 198,
667 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10,
668 ]);
669
670 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
671 let PublicParams::EdDSALegacy(EddsaLegacyPublicParams::Ed25519 { key }) =
672 pgp_key.public_params()
673 else {
674 panic!("Wrong type of public params");
675 };
676 assert_eq!(
677 key.to_bytes(),
678 [
679 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29,
680 198, 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10
681 ]
682 );
683
684 Ok(())
685 }
686
687 #[test]
688 fn convert_p256_to_pgp() -> TestResult {
689 let hsm_key = RawPublicKey::P256(vec![
690 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130, 169,
691 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240, 240, 134,
692 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122, 89, 2, 180, 2,
693 237, 15, 248, 104, 83, 142, 22, 185, 133,
694 ]);
695 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
696 let PublicParams::ECDSA(EcdsaPublicParams::P256 { key, .. }) = pgp_key.public_params()
697 else {
698 panic!("Wrong type of public params");
699 };
700 assert_eq!(
701 key.to_sec1_bytes().to_vec(),
702 [
703 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130,
704 169, 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240,
705 240, 134, 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122,
706 89, 2, 180, 2, 237, 15, 248, 104, 83, 142, 22, 185, 133
707 ]
708 );
709
710 Ok(())
711 }
712
713 #[test]
714 fn convert_p384_to_pgp() -> TestResult {
715 let hsm_key = RawPublicKey::P384(vec![
716 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72, 250,
717 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8, 66, 117,
718 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8, 75, 151, 252,
719 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82, 134, 134, 6, 17,
720 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139, 217, 90, 220, 239, 191,
721 148,
722 ]);
723 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
724 let PublicParams::ECDSA(EcdsaPublicParams::P384 { key, .. }) = pgp_key.public_params()
725 else {
726 panic!("Wrong type of public params");
727 };
728 assert_eq!(
729 key.to_sec1_bytes().to_vec(),
730 [
731 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72,
732 250, 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8,
733 66, 117, 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8,
734 75, 151, 252, 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82,
735 134, 134, 6, 17, 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139,
736 217, 90, 220, 239, 191, 148
737 ]
738 );
739
740 Ok(())
741 }
742
743 #[test]
744 fn convert_p521_to_pgp() -> TestResult {
745 let hsm_key = RawPublicKey::P521(vec![
746 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211, 118,
747 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96, 102, 55,
748 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26, 190, 40, 157,
749 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243, 67, 14, 159, 46,
750 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76, 198, 240, 32, 108, 48,
751 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10, 65, 118, 233, 79, 179, 90,
752 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102, 113, 26, 103, 127, 234, 47, 81,
753 ]);
754 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
755 let PublicParams::ECDSA(EcdsaPublicParams::P521 { key, .. }) = pgp_key.public_params()
756 else {
757 panic!("Wrong type of public params");
758 };
759 assert_eq!(
760 key.to_sec1_bytes().to_vec(),
761 [
762 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211,
763 118, 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96,
764 102, 55, 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26,
765 190, 40, 157, 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243,
766 67, 14, 159, 46, 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76,
767 198, 240, 32, 108, 48, 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10,
768 65, 118, 233, 79, 179, 90, 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102,
769 113, 26, 103, 127, 234, 47, 81
770 ]
771 );
772
773 Ok(())
774 }
775
776 #[test]
777 fn convert_rsa_to_pgp() -> TestResult {
778 let hsm_key = RawPublicKey::Rsa {
779 modulus: vec![
780 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
781 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
782 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
783 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
784 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
785 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
786 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
787 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
788 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
789 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
790 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
791 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
792 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
793 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
794 59, 161, 187,
795 ],
796 exponent: vec![1, 0, 1],
797 };
798 let pgp_key = hsm_key.to_openpgp_public_key(Timestamp::now())?;
799 let PublicParams::RSA(public) = pgp_key.public_params() else {
800 panic!("Wrong type of public params");
801 };
802 assert_eq!(public.key.e().to_bytes_be(), [1, 0, 1]);
803 assert_eq!(
804 public.key.n().to_bytes_be(),
805 [
806 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
807 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
808 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
809 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
810 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
811 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
812 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
813 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
814 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
815 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
816 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
817 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
818 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
819 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
820 59, 161, 187
821 ]
822 );
823
824 Ok(())
825 }
826
827 #[cfg(feature = "nethsm")]
829 mod nethsm {
830 use std::fs::File;
831
832 use base64ct::{Base64, Encoding as _};
833 use nethsm_sdk_rs::models::KeyPrivateData;
834
835 use super::*;
836
837 #[test]
838 fn private_key_import_ed25199_is_correctly_zero_padded() -> TestResult {
839 let key = SignedSecretKey::from_armor_single(File::open(
840 "tests/fixtures/ed25519-key-with-31-byte-private-key-scalar.asc",
841 )?)?
842 .0;
843
844 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
845
846 let data = Base64::decode_vec(&import.data.unwrap())?;
847
848 assert_eq!(data.len(), 32);
851 assert_eq!(data[0], 0x00);
852
853 Ok(())
854 }
855
856 #[test]
857 #[cfg(feature = "nethsm")]
858 fn private_key_import_rsa_key_with_nonstandard_moduli_is_read_correctly() -> TestResult {
859 let key = SignedSecretKey::from_armor_single(File::open(
860 "tests/fixtures/rsa-key-with-modulus-e-257.asc",
861 )?)?
862 .0;
863
864 let import: KeyPrivateData = tsk_to_private_key_import(&key)?.0.try_into()?;
865
866 let data = Base64::decode_vec(&import.public_exponent.unwrap())?;
867
868 assert_eq!(data, vec![0x01, 0x01]); Ok(())
872 }
873 }
874
875 struct Ed25519SoftKey {
877 signing_key: SigningKey,
879
880 certificate: Option<Vec<u8>>,
882 }
883
884 impl Ed25519SoftKey {
885 fn new() -> Self {
889 Self {
890 signing_key: SigningKey::generate(&mut OsRng),
893 certificate: None,
894 }
895 }
896 }
897
898 impl RawSigningKey for Ed25519SoftKey {
899 fn key_id(&self) -> String {
901 "Software key".into()
902 }
903
904 fn sign(&self, digest: &[u8]) -> Result<Vec<Vec<u8>>, crate::Error> {
910 let signature = self.signing_key.sign(digest);
911 Ok(vec![signature.r_bytes().into(), signature.s_bytes().into()])
912 }
913
914 fn certificate(&self) -> Result<Option<Vec<u8>>, crate::Error> {
920 Ok(self.certificate.clone())
921 }
922
923 fn public(&self) -> Result<RawPublicKey, crate::Error> {
929 Ok(RawPublicKey::Ed25519(
930 self.signing_key.verifying_key().to_bytes().into(),
931 ))
932 }
933 }
934
935 #[test]
936 fn sign_dummy() -> TestResult {
937 let mut raw_signer = Ed25519SoftKey::new();
938
939 let cert = add_certificate(
940 &raw_signer,
941 Default::default(),
942 OpenPgpUserId::new("test".into())?,
943 Timestamp::now(),
944 Default::default(),
945 )?;
946
947 raw_signer.certificate = Some(cert);
948
949 let mut data_to_sign = [0; 32];
950 OsRng::fill_bytes(&mut OsRng, &mut data_to_sign);
951
952 let signature = sign(&raw_signer, &data_to_sign)?;
953 assert!(!signature.is_empty());
954
955 Ok(())
956 }
957
958 #[rstest::rstest]
959 #[case::p256(ECCCurve::P256, KeyType::EcP256)]
960 #[case::p384(ECCCurve::P384, KeyType::EcP384)]
961 #[case::p521(ECCCurve::P521, KeyType::EcP521)]
962 fn import_ecdsa(#[case] pgp_curve: ECCCurve, #[case] expected_type: KeyType) -> TestResult {
963 let params = SecretKeyParamsBuilder::default()
964 .key_type(ComposedKeyType::ECDSA(pgp_curve))
965 .can_sign(true)
966 .build()?;
967
968 let rng = OsRng;
969
970 let key = params.generate(rng)?;
971 let actual_type = tsk_to_private_key_import(&key)?.0.key_type();
972 assert_eq!(actual_type, expected_type);
973
974 Ok(())
975 }
976
977 #[test]
978 fn test_unsupported_ecdsa_curve() -> TestResult {
979 let key = SecretKeyParamsBuilder::default()
980 .key_type(ComposedKeyType::ECDSA(ECCCurve::Secp256k1))
981 .can_sign(true)
982 .build()?
983 .generate(OsRng)?;
984
985 assert!(tsk_to_private_key_import(&key).is_err());
986
987 Ok(())
988 }
989}