1use std::{backtrace::Backtrace, io::Cursor};
4
5use chrono::{DateTime, Utc};
6use digest::DynDigest;
7use ed25519_dalek::VerifyingKey;
8use log::{error, warn};
9pub use pgp::composed::{Deserializable, SignedSecretKey};
11use pgp::{
12 composed::{ArmorOptions, DetachedSignature, SignedPublicKey},
13 crypto::{hash::HashAlgorithm, public_key::PublicKeyAlgorithm},
14 packet::{
15 Notation,
16 PacketTrait,
17 PubKeyInner,
18 PublicKey,
19 Signature,
20 SignatureConfig,
21 SignatureType,
22 Subpacket,
23 SubpacketData,
24 UserId,
25 },
26 ser::Serialize,
27 types::{
28 CompressionAlgorithm,
29 EcdsaPublicParams,
30 KeyDetails as _,
31 KeyId,
32 KeyVersion,
33 Mpi,
34 Password,
35 PlainSecretParams,
36 PublicKeyTrait as _,
37 PublicParams,
38 RsaPublicParams,
39 SecretKeyTrait,
40 SecretParams,
41 SignatureBytes,
42 },
43};
44use rsa::BigUint;
45use rsa::traits::PublicKeyParts as _;
46use sha2::digest::Digest as _;
47
48use crate::{
49 key::{KeyMechanism, KeyType, PrivateKeyImport, key_type_matches_length},
50 openpgp::{OpenPgpKeyUsageFlags, OpenPgpUserId, OpenPgpVersion},
51 signer::{
52 error::Error,
53 traits::{RawPublicKey, RawSigningKey},
54 },
55};
56
57struct SigningKey<'a> {
62 public_key: PublicKey,
63 raw_signer: &'a dyn RawSigningKey,
64}
65
66impl std::fmt::Debug for SigningKey<'_> {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.debug_struct("SigningKey")
69 .field("public_key", &self.public_key)
70 .finish()
71 }
72}
73
74#[inline]
80fn to_rpgp_error(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> pgp::errors::Error {
81 pgp::errors::Error::IO {
82 source: std::io::Error::other(e),
83 backtrace: Some(Backtrace::capture()),
84 }
85}
86
87impl<'a> SigningKey<'a> {
88 fn new(raw_signer: &'a dyn RawSigningKey, public_key: PublicKey) -> Self {
90 Self {
91 raw_signer,
92 public_key,
93 }
94 }
95
96 fn new_provisioned(raw_signer: &'a dyn RawSigningKey) -> Result<Self, Error> {
109 let public_key = if let Some(cert) = raw_signer.certificate()?.as_ref() {
110 SignedPublicKey::from_bytes(Cursor::new(cert))?.primary_key
111 } else {
112 return Err(Error::OpenPpgCertificateMissing);
113 };
114 Ok(Self::new(raw_signer, public_key))
115 }
116}
117
118impl pgp::types::KeyDetails for SigningKey<'_> {
119 fn version(&self) -> KeyVersion {
120 self.public_key.version()
121 }
122
123 fn fingerprint(&self) -> pgp::types::Fingerprint {
124 self.public_key.fingerprint()
125 }
126
127 fn key_id(&self) -> KeyId {
128 self.public_key.key_id()
129 }
130
131 fn algorithm(&self) -> PublicKeyAlgorithm {
132 self.public_key.algorithm()
133 }
134}
135
136impl SecretKeyTrait for SigningKey<'_> {
137 fn create_signature(
155 &self,
156 _key_pw: &Password,
157 hash: HashAlgorithm,
158 data: &[u8],
159 ) -> pgp::errors::Result<SignatureBytes> {
160 if hash != self.hash_alg() {
161 error!(
162 "Requested signing hash is different from the default supported, got {hash} expected {expected}",
163 expected = self.hash_alg()
164 );
165 return Err(to_rpgp_error(Error::UnsupportedHashAlgorithm {
166 actual: hash,
167 expected: self.hash_alg(),
168 }));
169 }
170 let sig = self.raw_signer.sign(data).map_err(|e| {
171 error!("RawSigner::sign failed: {e:?}");
172 to_rpgp_error(e)
173 })?;
174
175 Ok(SignatureBytes::Mpis(
176 sig.into_iter().map(|b| Mpi::from_slice(&b)).collect(),
177 ))
178 }
179
180 fn hash_alg(&self) -> HashAlgorithm {
186 HashAlgorithm::Sha512
187 }
188}
189
190pub fn add_certificate(
200 raw_signer: &dyn RawSigningKey,
201 flags: OpenPgpKeyUsageFlags,
202 user_id: OpenPgpUserId,
203 created_at: DateTime<Utc>,
204 version: OpenPgpVersion,
205) -> Result<Vec<u8>, Error> {
206 if version != OpenPgpVersion::V4 {
207 return Err(crate::openpgp::Error::InvalidOpenPgpVersion(version.to_string()).into());
208 }
209 let public_key = raw_signer.public()?.to_openpgp_public_key(created_at)?;
210 let signer = SigningKey::new(raw_signer, public_key.clone());
211
212 let composed_pk = pgp::composed::PublicKey::new(
213 public_key.clone(),
214 pgp::composed::KeyDetails::new(
215 Some(UserId::from_str(Default::default(), user_id.as_ref())?),
216 vec![],
217 vec![],
218 flags.into(),
219 Default::default(),
220 Default::default(),
221 Default::default(),
222 vec![CompressionAlgorithm::Uncompressed].into(),
223 vec![].into(),
224 ),
225 vec![],
226 );
227
228 let signed_pk =
229 composed_pk.sign(rand::thread_rng(), &signer, &public_key, &Password::empty())?;
230
231 let mut buffer = vec![];
232 signed_pk.to_writer(&mut buffer)?;
233 Ok(buffer)
234}
235
236pub fn tsk_to_private_key_import(
246 key: &SignedSecretKey,
247) -> Result<(PrivateKeyImport, KeyMechanism), Error> {
248 if !key.secret_subkeys.is_empty() {
249 return Err(Error::OpenPgpTskContainsMultipleComponentKeys {
250 fingerprint: key.fingerprint(),
251 });
252 }
253 let SecretParams::Plain(secret) = key.primary_key.secret_params() else {
254 return Err(Error::OpenPgpTskIsPassphraseProtected {
255 fingerprint: key.fingerprint(),
256 });
257 };
258 Ok(match (secret, key.public_key().public_params()) {
259 (PlainSecretParams::RSA(secret), PublicParams::RSA(public)) => {
260 key_type_matches_length(
262 KeyType::Rsa,
263 Some(public.key.n().to_bytes_be().len() as u32 * 8),
264 )?;
265
266 let (_d, p, q, _u) = secret.to_bytes();
267
268 (
269 PrivateKeyImport::from_rsa(p, q, public.key.e().to_bytes_be().to_vec()),
270 KeyMechanism::RsaSignaturePkcs1,
271 )
272 }
273 (PlainSecretParams::ECDSA(secret_key), _) => {
274 let ec = if let PublicParams::ECDSA(pp) = key.primary_key.public_key().public_params() {
275 match pp {
276 EcdsaPublicParams::P256 { .. } => KeyType::EcP256,
277 EcdsaPublicParams::P384 { .. } => KeyType::EcP384,
278 EcdsaPublicParams::P521 { .. } => KeyType::EcP521,
279 pp => {
280 warn!("Unsupported ECDSA parameters: {pp:?}");
281 return Err(Error::UnsupportedKeyFormat {
282 context: "converting ECDSA key to private key import",
283 public_params: Box::new(key.public_key().public_params().clone()),
284 })?;
285 }
286 }
287 } else {
288 return Err(Error::UnsupportedKeyFormat {
289 context: "converting non-ECDSA key to private key import",
290 public_params: Box::new(key.public_key().public_params().clone()),
291 });
292 };
293
294 let bytes = match secret_key {
295 pgp::crypto::ecdsa::SecretKey::P256(secret_key) => secret_key.to_bytes().to_vec(),
296 pgp::crypto::ecdsa::SecretKey::P384(secret_key) => secret_key.to_bytes().to_vec(),
297 pgp::crypto::ecdsa::SecretKey::P521(secret_key) => secret_key.to_bytes().to_vec(),
298
299 pgp::crypto::ecdsa::SecretKey::Secp256k1(secret_key) => {
300 secret_key.to_bytes().to_vec()
301 }
302 secret_key => {
303 warn!("Unsupported secret key parameters: {secret_key:?}");
304 return Err(Error::UnsupportedKeyFormat {
305 context: "converting unsupported ECDSA key to private key import",
306 public_params: Box::new(key.public_key().public_params().clone()),
307 })?;
308 }
309 };
310
311 (
312 PrivateKeyImport::from_raw_bytes(ec, bytes).map_err(to_rpgp_error)?,
313 KeyMechanism::EcdsaSignature,
314 )
315 }
316 (PlainSecretParams::Ed25519Legacy(bytes), _) => (
317 PrivateKeyImport::from_raw_bytes(KeyType::Curve25519, bytes.as_bytes())
318 .map_err(to_rpgp_error)?,
319 KeyMechanism::EdDsaSignature,
320 ),
321 (_, public_params) => {
322 return Err(Error::UnsupportedKeyFormat {
323 context: "converting unknown key format to private key import",
324 public_params: Box::new(public_params.clone()),
325 });
326 }
327 })
328}
329
330pub fn sign(raw_signer: &dyn RawSigningKey, message: &[u8]) -> Result<Vec<u8>, Error> {
349 let signer = SigningKey::new_provisioned(raw_signer)?;
350
351 let mut sig_config =
352 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
353 sig_config.hashed_subpackets = vec![
354 Subpacket::regular(SubpacketData::SignatureCreationTime(
355 std::time::SystemTime::now().into(),
356 ))?,
357 Subpacket::regular(SubpacketData::Issuer(signer.key_id()))?,
358 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))?,
359 ];
360
361 let mut hasher = sig_config.hash_alg.new_hasher().map_err(to_rpgp_error)?;
362 sig_config.hash_data_to_sign(&mut hasher, message)?;
363
364 let len = sig_config.hash_signature_data(&mut hasher)?;
365
366 hasher.update(&sig_config.trailer(len)?);
367
368 let hash = &hasher.finalize()[..];
369
370 let signed_hash_value = [hash[0], hash[1]];
371 let raw_sig = signer.create_signature(&Password::empty(), sig_config.hash_alg, hash)?;
372
373 let signature = Signature::from_config(sig_config, signed_hash_value, raw_sig)?;
374
375 let mut out = vec![];
376 signature.to_writer_with_header(&mut out)?;
377
378 Ok(out)
379}
380
381#[derive(Clone, Default)]
391struct Hasher(sha2::Sha512);
392
393impl DynDigest for Hasher {
394 fn update(&mut self, data: &[u8]) {
398 self.0.update(data);
399 }
400
401 fn finalize_into(self, buf: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
407 sha2::digest::DynDigest::finalize_into(self.0, buf)
408 .map_err(|_| digest::InvalidBufferSize)?;
409 Ok(())
410 }
411
412 fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), digest::InvalidBufferSize> {
418 sha2::digest::DynDigest::finalize_into_reset(&mut self.0, out)
419 .map_err(|_| digest::InvalidBufferSize)?;
420 Ok(())
421 }
422
423 fn reset(&mut self) {
425 sha2::digest::DynDigest::reset(&mut self.0)
426 }
427
428 fn output_size(&self) -> usize {
430 sha2::digest::DynDigest::output_size(&self.0)
431 }
432
433 fn box_clone(&self) -> Box<dyn DynDigest> {
435 Box::new(self.clone())
436 }
437}
438
439pub fn sign_hasher_state(
458 raw_signer: &dyn RawSigningKey,
459 state: sha2::Sha512,
460) -> Result<String, Error> {
461 let signer = SigningKey::new_provisioned(raw_signer)?;
462 let hasher = state.clone();
463
464 let file_hash = Box::new(hasher).finalize().to_vec();
465
466 let sig_config = {
467 let mut sig_config =
468 SignatureConfig::v4(SignatureType::Binary, signer.algorithm(), signer.hash_alg());
469 sig_config.hashed_subpackets = vec![
470 Subpacket::regular(SubpacketData::SignatureCreationTime(
471 std::time::SystemTime::now().into(),
472 ))?,
473 Subpacket::regular(SubpacketData::Issuer(signer.key_id()))?,
474 Subpacket::regular(SubpacketData::IssuerFingerprint(signer.fingerprint()))?,
475 Subpacket::regular(SubpacketData::Notation(Notation {
476 readable: false,
477 name: "data-digest@archlinux.org".into(),
478 value: file_hash.into(),
479 }))?,
480 ];
481 sig_config
482 };
483
484 let mut hasher = Box::new(Hasher(state.clone())) as Box<dyn DynDigest + Send>;
485
486 let len = sig_config.hash_signature_data(&mut hasher)?;
487
488 hasher.update(&sig_config.trailer(len)?);
489
490 let hash = &hasher.finalize()[..];
491
492 let signed_hash_value = [hash[0], hash[1]];
493
494 let raw_sig = signer.create_signature(&Password::empty(), sig_config.hash_alg, hash)?;
495
496 let signature = pgp::packet::Signature::from_config(sig_config, signed_hash_value, raw_sig)?;
497
498 let signature = DetachedSignature { signature };
499 Ok(signature.to_armored_string(ArmorOptions::default())?)
500}
501
502fn ecdsa_to_public_key(
513 created_at: DateTime<Utc>,
514 key: EcdsaPublicParams,
515) -> Result<PublicKey, Error> {
516 Ok(PublicKey::from_inner(PubKeyInner::new(
517 KeyVersion::V4,
518 PublicKeyAlgorithm::ECDSA,
519 created_at,
520 None,
521 PublicParams::ECDSA(key),
522 )?)?)
523}
524
525impl RawPublicKey {
526 fn to_openpgp_public_key(&self, created_at: DateTime<Utc>) -> Result<PublicKey, Error> {
542 Ok(match self {
543 RawPublicKey::Rsa { modulus, exponent } => PublicKey::from_inner(PubKeyInner::new(
544 KeyVersion::V4,
545 PublicKeyAlgorithm::RSA,
546 created_at,
547 None,
548 PublicParams::RSA(RsaPublicParams {
549 key: rsa::RsaPublicKey::new(
550 BigUint::from_bytes_be(modulus),
551 BigUint::from_bytes_be(exponent),
552 )
553 .map_err(to_rpgp_error)?,
554 }),
555 )?)?,
556
557 RawPublicKey::Ed25519(pubkey) => PublicKey::from_inner(PubKeyInner::new(
558 KeyVersion::V4,
559 PublicKeyAlgorithm::EdDSALegacy,
560 created_at,
561 None,
562 PublicParams::EdDSALegacy(pgp::types::EddsaLegacyPublicParams::Ed25519 {
563 key: VerifyingKey::from_bytes(&pubkey[..].try_into().map_err(to_rpgp_error)?)
564 .map_err(to_rpgp_error)?,
565 }),
566 )?)?,
567
568 RawPublicKey::P256(pubkey) => ecdsa_to_public_key(
569 created_at,
570 EcdsaPublicParams::P256 {
571 key: p256::PublicKey::from_sec1_bytes(pubkey)?,
572 },
573 )?,
574
575 RawPublicKey::P384(pubkey) => ecdsa_to_public_key(
576 created_at,
577 EcdsaPublicParams::P384 {
578 key: p384::PublicKey::from_sec1_bytes(pubkey)?,
579 },
580 )?,
581
582 RawPublicKey::P521(pubkey) => ecdsa_to_public_key(
583 created_at,
584 EcdsaPublicParams::P521 {
585 key: p521::PublicKey::from_sec1_bytes(pubkey)?,
586 },
587 )?,
588 })
589 }
590}
591
592pub fn extract_certificate(key: SignedSecretKey) -> Result<Vec<u8>, Error> {
605 let public: SignedPublicKey = key.into();
606 let mut buffer = vec![];
607 public.to_writer(&mut buffer)?;
608 Ok(buffer)
609}
610
611#[cfg(test)]
612mod tests {
613 use std::time::SystemTime;
614
615 use base64ct::{Base64, Encoding as _};
616 use ed25519_dalek::{Signer, SigningKey};
617 use pgp::{
618 composed::SecretKeyParamsBuilder,
619 crypto::ecc_curve::ECCCurve,
620 types::{EcdsaPublicParams, PublicParams},
621 };
622 use rand::RngCore;
623 use rsa::rand_core::OsRng;
624 use testresult::TestResult;
625
626 use super::*;
627
628 #[test]
629 fn convert_ed25519_to_pgp() -> TestResult {
630 let hsm_key = RawPublicKey::Ed25519(vec![
631 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29, 198,
632 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10,
633 ]);
634
635 let pgp_key = hsm_key.to_openpgp_public_key(DateTime::UNIX_EPOCH)?;
636 let PublicParams::EdDSALegacy(pgp::types::EddsaLegacyPublicParams::Ed25519 { key }) =
637 pgp_key.public_params()
638 else {
639 panic!("Wrong type of public params");
640 };
641 assert_eq!(
642 key.to_bytes(),
643 [
644 252, 224, 232, 104, 60, 215, 247, 16, 227, 167, 29, 139, 125, 29, 3, 8, 136, 29,
645 198, 163, 167, 117, 143, 109, 186, 65, 5, 45, 80, 142, 109, 10
646 ]
647 );
648
649 Ok(())
650 }
651
652 #[test]
653 fn convert_p256_to_pgp() -> TestResult {
654 let hsm_key = RawPublicKey::P256(vec![
655 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130, 169,
656 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240, 240, 134,
657 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122, 89, 2, 180, 2,
658 237, 15, 248, 104, 83, 142, 22, 185, 133,
659 ]);
660 let pgp_key = hsm_key.to_openpgp_public_key(DateTime::UNIX_EPOCH)?;
661 let PublicParams::ECDSA(EcdsaPublicParams::P256 { key, .. }) = pgp_key.public_params()
662 else {
663 panic!("Wrong type of public params");
664 };
665 assert_eq!(
666 key.to_sec1_bytes().to_vec(),
667 [
668 4, 222, 106, 236, 96, 145, 243, 13, 81, 181, 119, 76, 5, 29, 72, 112, 134, 130,
669 169, 182, 231, 247, 107, 204, 228, 178, 45, 77, 196, 91, 117, 122, 57, 69, 240,
670 240, 134, 114, 138, 232, 63, 45, 141, 102, 164, 169, 118, 214, 99, 215, 138, 122,
671 89, 2, 180, 2, 237, 15, 248, 104, 83, 142, 22, 185, 133
672 ]
673 );
674
675 Ok(())
676 }
677
678 #[test]
679 fn convert_p384_to_pgp() -> TestResult {
680 let hsm_key = RawPublicKey::P384(vec![
681 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72, 250,
682 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8, 66, 117,
683 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8, 75, 151, 252,
684 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82, 134, 134, 6, 17,
685 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139, 217, 90, 220, 239, 191,
686 148,
687 ]);
688 let pgp_key = hsm_key.to_openpgp_public_key(DateTime::UNIX_EPOCH)?;
689 let PublicParams::ECDSA(EcdsaPublicParams::P384 { key, .. }) = pgp_key.public_params()
690 else {
691 panic!("Wrong type of public params");
692 };
693 assert_eq!(
694 key.to_sec1_bytes().to_vec(),
695 [
696 4, 127, 136, 147, 111, 187, 191, 131, 84, 166, 118, 67, 76, 107, 52, 142, 175, 72,
697 250, 64, 197, 76, 154, 162, 48, 211, 135, 63, 153, 60, 213, 168, 40, 41, 111, 8, 8,
698 66, 117, 221, 162, 244, 233, 210, 205, 206, 70, 64, 116, 30, 98, 186, 88, 17, 8,
699 75, 151, 252, 123, 98, 182, 40, 183, 6, 28, 110, 29, 53, 15, 90, 227, 116, 185, 82,
700 134, 134, 6, 17, 117, 218, 83, 181, 230, 154, 106, 235, 244, 112, 227, 231, 139,
701 217, 90, 220, 239, 191, 148
702 ]
703 );
704
705 Ok(())
706 }
707
708 #[test]
709 fn convert_p521_to_pgp() -> TestResult {
710 let hsm_key = RawPublicKey::P521(vec![
711 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211, 118,
712 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96, 102, 55,
713 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26, 190, 40, 157,
714 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243, 67, 14, 159, 46,
715 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76, 198, 240, 32, 108, 48,
716 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10, 65, 118, 233, 79, 179, 90,
717 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102, 113, 26, 103, 127, 234, 47, 81,
718 ]);
719 let pgp_key = hsm_key.to_openpgp_public_key(DateTime::UNIX_EPOCH)?;
720 let PublicParams::ECDSA(EcdsaPublicParams::P521 { key, .. }) = pgp_key.public_params()
721 else {
722 panic!("Wrong type of public params");
723 };
724 assert_eq!(
725 key.to_sec1_bytes().to_vec(),
726 [
727 4, 1, 33, 39, 193, 238, 201, 51, 127, 12, 24, 192, 161, 112, 247, 31, 184, 211,
728 118, 95, 147, 192, 236, 9, 222, 214, 138, 194, 173, 170, 248, 123, 1, 138, 201, 96,
729 102, 55, 160, 212, 150, 101, 58, 235, 53, 50, 30, 47, 136, 171, 244, 138, 236, 26,
730 190, 40, 157, 208, 63, 92, 170, 195, 182, 80, 114, 205, 253, 1, 211, 88, 102, 243,
731 67, 14, 159, 46, 35, 89, 188, 38, 134, 184, 208, 223, 213, 206, 126, 106, 33, 76,
732 198, 240, 32, 108, 48, 124, 170, 158, 30, 4, 11, 37, 233, 254, 171, 163, 153, 10,
733 65, 118, 233, 79, 179, 90, 185, 21, 71, 99, 21, 47, 223, 100, 224, 196, 110, 102,
734 113, 26, 103, 127, 234, 47, 81
735 ]
736 );
737
738 Ok(())
739 }
740
741 #[test]
742 fn convert_rsa_to_pgp() -> TestResult {
743 let hsm_key = RawPublicKey::Rsa {
744 modulus: vec![
745 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
746 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
747 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
748 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
749 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
750 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
751 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
752 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
753 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
754 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
755 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
756 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
757 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
758 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
759 59, 161, 187,
760 ],
761 exponent: vec![1, 0, 1],
762 };
763 let pgp_key = hsm_key.to_openpgp_public_key(DateTime::UNIX_EPOCH)?;
764 let PublicParams::RSA(public) = pgp_key.public_params() else {
765 panic!("Wrong type of public params");
766 };
767 assert_eq!(public.key.e().to_bytes_be(), [1, 0, 1]);
768 assert_eq!(
769 public.key.n().to_bytes_be(),
770 [
771 227, 127, 58, 151, 86, 130, 213, 238, 13, 247, 122, 241, 51, 227, 105, 143, 231,
772 114, 208, 33, 152, 209, 109, 207, 53, 179, 147, 4, 100, 99, 238, 212, 196, 126, 89,
773 4, 151, 106, 177, 219, 21, 187, 147, 41, 158, 242, 194, 208, 67, 252, 177, 135, 34,
774 120, 154, 170, 63, 130, 4, 125, 56, 55, 239, 99, 43, 115, 198, 196, 191, 159, 243,
775 13, 103, 7, 64, 76, 96, 184, 64, 48, 99, 62, 254, 248, 179, 254, 117, 156, 47, 224,
776 100, 122, 189, 87, 59, 216, 171, 118, 230, 23, 71, 180, 88, 216, 151, 69, 61, 233,
777 231, 118, 104, 126, 107, 245, 8, 16, 207, 4, 64, 235, 172, 154, 183, 50, 175, 142,
778 223, 228, 199, 243, 251, 171, 220, 227, 140, 130, 243, 113, 216, 32, 224, 195, 4,
779 53, 88, 100, 150, 221, 114, 19, 55, 215, 164, 102, 154, 35, 254, 31, 28, 195, 17,
780 100, 207, 153, 99, 155, 40, 2, 45, 27, 87, 116, 213, 171, 205, 82, 70, 91, 113,
781 185, 47, 242, 115, 246, 199, 82, 124, 77, 173, 201, 191, 62, 223, 93, 136, 84, 82,
782 121, 239, 55, 47, 71, 40, 42, 2, 73, 18, 215, 91, 152, 32, 252, 110, 161, 166, 211,
783 232, 130, 124, 74, 148, 156, 126, 169, 109, 26, 197, 55, 142, 32, 11, 43, 33, 81,
784 87, 159, 8, 247, 82, 148, 149, 119, 160, 141, 69, 81, 223, 81, 49, 21, 205, 30, 0,
785 59, 161, 187
786 ]
787 );
788
789 Ok(())
790 }
791
792 #[test]
793 fn private_key_import_ed25199_is_correctly_zero_padded() -> TestResult {
794 let key = SignedSecretKey::from_armor_single(std::fs::File::open(
795 "tests/fixtures/ed25519-key-with-31-byte-private-key-scalar.asc",
796 )?)?
797 .0;
798
799 let import: nethsm_sdk_rs::models::KeyPrivateData =
800 tsk_to_private_key_import(&key)?.0.into();
801
802 let data = Base64::decode_vec(&import.data.unwrap())?;
803
804 assert_eq!(data.len(), 32);
807 assert_eq!(data[0], 0x00);
808
809 Ok(())
810 }
811
812 #[test]
813 fn private_key_import_rsa_key_with_nonstandard_moduli_is_read_correctly() -> TestResult {
814 let key = SignedSecretKey::from_armor_single(std::fs::File::open(
815 "tests/fixtures/rsa-key-with-modulus-e-257.asc",
816 )?)?
817 .0;
818
819 let import: nethsm_sdk_rs::models::KeyPrivateData =
820 tsk_to_private_key_import(&key)?.0.into();
821
822 let data = Base64::decode_vec(&import.public_exponent.unwrap())?;
823
824 assert_eq!(data, vec![0x01, 0x01]); Ok(())
828 }
829
830 struct Ed25519SoftKey {
832 signing_key: SigningKey,
834
835 certificate: Option<Vec<u8>>,
837 }
838
839 impl Ed25519SoftKey {
840 fn new() -> Self {
844 Self {
845 signing_key: SigningKey::generate(&mut OsRng),
848 certificate: None,
849 }
850 }
851 }
852
853 impl RawSigningKey for Ed25519SoftKey {
854 fn key_id(&self) -> String {
856 "Software key".into()
857 }
858
859 fn sign(&self, digest: &[u8]) -> Result<Vec<Vec<u8>>, Error> {
865 let signature = self.signing_key.sign(digest);
866 Ok(vec![signature.r_bytes().into(), signature.s_bytes().into()])
867 }
868
869 fn certificate(&self) -> Result<Option<Vec<u8>>, Error> {
875 Ok(self.certificate.clone())
876 }
877
878 fn public(&self) -> Result<RawPublicKey, Error> {
884 Ok(RawPublicKey::Ed25519(
885 self.signing_key.verifying_key().to_bytes().into(),
886 ))
887 }
888 }
889
890 #[test]
891 fn sign_dummy() -> TestResult {
892 let mut raw_signer = Ed25519SoftKey::new();
893
894 let cert = add_certificate(
895 &raw_signer,
896 Default::default(),
897 OpenPgpUserId::new("test".into())?,
898 SystemTime::now().into(),
899 Default::default(),
900 )?;
901
902 raw_signer.certificate = Some(cert);
903
904 let mut data_to_sign = [0; 32];
905 OsRng::fill_bytes(&mut OsRng, &mut data_to_sign);
906
907 let signature = sign(&raw_signer, &data_to_sign)?;
908 assert!(!signature.is_empty());
909
910 Ok(())
911 }
912
913 #[rstest::rstest]
914 #[case::p256(ECCCurve::P256, KeyType::EcP256)]
915 #[case::p384(ECCCurve::P384, KeyType::EcP384)]
916 #[case::p521(ECCCurve::P521, KeyType::EcP521)]
917 fn import_ecdsa(#[case] pgp_curve: ECCCurve, #[case] expected_type: KeyType) -> TestResult {
918 let params = SecretKeyParamsBuilder::default()
919 .key_type(pgp::composed::KeyType::ECDSA(pgp_curve))
920 .can_sign(true)
921 .build()?;
922
923 let rng = rsa::rand_core::OsRng;
924
925 let key = params.generate(rng)?.sign(rng, &Default::default())?;
926 let actual_type = tsk_to_private_key_import(&key)?.0.key_type();
927 assert_eq!(actual_type, expected_type);
928
929 Ok(())
930 }
931
932 #[test]
933 fn test_unsupported_ecdsa_curve() -> TestResult {
934 let key = SecretKeyParamsBuilder::default()
935 .key_type(pgp::composed::KeyType::ECDSA(ECCCurve::Secp256k1))
936 .can_sign(true)
937 .build()?
938 .generate(rsa::rand_core::OsRng)?
939 .sign(rsa::rand_core::OsRng, &Default::default())?;
940
941 assert!(tsk_to_private_key_import(&key).is_err());
942
943 Ok(())
944 }
945}