1use super::{
10 Algorithm, CryptoError, HashContext, HashImpl, HashOutput, Sha1, Sha256, Sha512, SigningKey,
11 VerifyingKey,
12 aws_lc_mldsa::MlDsa44,
13 composite::{
14 self, ED25519_PUBLIC_KEY_LEN, LABEL, PUBLIC_KEY_LEN, PrivateKey, PublicKey, SIGNATURE_LEN,
15 Seed, library_error, message_representative,
16 },
17 rsa_private_key_heap_size,
18};
19use crate::{
20 Error, Result,
21 dkim::Canonicalization,
22 headers::{Writable, Writer},
23};
24use aws_lc_rs::digest::{Context, SHA1_FOR_LEGACY_USE_ONLY, SHA256, SHA512};
25use aws_lc_rs::rand::SystemRandom;
26use aws_lc_rs::signature::{
27 ED25519, Ed25519KeyPair, KeyPair, RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
28 RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, RSA_PKCS1_SHA256, RsaKeyPair,
29 UnparsedPublicKey,
30};
31use rustls_pki_types::{PrivateKeyDer, PrivatePkcs1KeyDer, PrivatePkcs8KeyDer, pem::PemObject};
32use std::marker::PhantomData;
33
34const ED25519_PRIVATE_KEY_HEAP_SIZE: usize = 112;
35const MLDSA44_PRIVATE_KEY_HEAP_SIZE: usize = 4096;
36const MLDSA44_PUBLIC_KEY_HEAP_SIZE: usize = 1600;
37
38#[derive(Debug)]
43pub struct RsaKey<T> {
44 inner: RsaKeyPair,
45 rng: SystemRandom,
46 padding: PhantomData<T>,
47}
48
49impl<T: HashImpl> RsaKey<T> {
50 #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
57 pub fn from_pkcs8_pem(pkcs8_pem: &str) -> Result<Self> {
58 Self::from_key_der(PrivateKeyDer::Pkcs8(
59 PrivatePkcs8KeyDer::from_pem_slice(pkcs8_pem.as_bytes())
60 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
61 ))
62 }
63
64 #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
71 pub fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self> {
72 Self::from_key_der(PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(pkcs8_der)))
73 }
74
75 #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
83 pub fn from_rsa_pem(rsa_pem: &str) -> Result<Self> {
84 Self::from_key_der(PrivateKeyDer::Pkcs1(
85 PrivatePkcs1KeyDer::from_pem_slice(rsa_pem.as_bytes())
86 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
87 ))
88 }
89
90 #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
97 pub fn from_der(der: &[u8]) -> Result<Self> {
98 Self::from_key_der(PrivateKeyDer::Pkcs1(PrivatePkcs1KeyDer::from(der)))
99 }
100
101 pub fn from_key_der(key_der: PrivateKeyDer<'_>) -> Result<Self> {
110 let inner = match key_der {
111 PrivateKeyDer::Pkcs1(der) => RsaKeyPair::from_der(der.secret_pkcs1_der())
112 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
113 PrivateKeyDer::Pkcs8(der) => RsaKeyPair::from_pkcs8(der.secret_pkcs8_der())
114 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
115 _ => {
116 return Err(Error::Crypto(CryptoError::Library(
117 "Unsupported RSA key format".to_string(),
118 )));
119 }
120 };
121
122 Ok(Self {
123 inner,
124 rng: SystemRandom::new(),
125 padding: PhantomData,
126 })
127 }
128
129 pub fn public_key(&self) -> Vec<u8> {
132 self.inner.public_key().as_ref().to_vec()
133 }
134}
135
136impl SigningKey for RsaKey<Sha256> {
137 type Hasher = Sha256;
138
139 fn sign(&self, input: impl Writable) -> Result<Vec<u8>> {
140 let mut data = Vec::with_capacity(256);
141 input.write(&mut data);
142
143 let mut signature = vec![0; self.inner.public_key().modulus_len()];
144 self.inner
145 .sign(&RSA_PKCS1_SHA256, &self.rng, &data, &mut signature)
146 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?;
147 Ok(signature)
148 }
149
150 fn algorithm(&self) -> Algorithm {
151 Algorithm::RsaSha256
152 }
153
154 fn heap_size(&self) -> usize {
155 rsa_private_key_heap_size(self.inner.public_key().modulus_len())
156 }
157}
158
159pub struct Ed25519Key {
164 inner: Ed25519KeyPair,
165}
166
167impl Ed25519Key {
168 pub fn generate_pkcs8() -> Result<Vec<u8>> {
176 Ok(Ed25519KeyPair::generate_pkcs8(&SystemRandom::new())
177 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?
178 .as_ref()
179 .to_vec())
180 }
181
182 pub fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self> {
192 Ok(Self {
193 inner: Ed25519KeyPair::from_pkcs8(pkcs8_der)
194 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
195 })
196 }
197
198 pub fn from_pkcs8_maybe_unchecked_der(pkcs8_der: &[u8]) -> Result<Self> {
208 Ok(Self {
209 inner: Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8_der)
210 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
211 })
212 }
213
214 pub fn from_seed_and_public_key(seed: &[u8], public_key: &[u8]) -> Result<Self> {
222 Ok(Self {
223 inner: Ed25519KeyPair::from_seed_and_public_key(seed, public_key)
224 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
225 })
226 }
227
228 pub fn public_key(&self) -> Vec<u8> {
231 self.inner.public_key().as_ref().to_vec()
232 }
233}
234
235impl SigningKey for Ed25519Key {
236 type Hasher = Sha256;
237
238 fn sign(&self, input: impl Writable) -> Result<Vec<u8>> {
239 let mut data = Sha256::hasher();
240 input.write(&mut data);
241 Ok(self.inner.sign(data.complete().as_ref()).as_ref().to_vec())
242 }
243
244 fn algorithm(&self) -> Algorithm {
245 Algorithm::Ed25519Sha256
246 }
247
248 fn heap_size(&self) -> usize {
249 ED25519_PRIVATE_KEY_HEAP_SIZE
250 }
251}
252
253pub(crate) struct RsaPublicKey {
254 key: Vec<u8>,
255}
256
257impl RsaPublicKey {
258 pub(crate) fn verifying_key_from_bytes(
259 bytes: &[u8],
260 ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
261 Ok(Box::new(Self {
262 key: try_strip_rsa_prefix(bytes).unwrap_or(bytes).to_vec(),
263 }))
264 }
265}
266
267fn rsa_modulus_bits(key: &[u8]) -> Option<usize> {
269 if *key.first()? != DER_SEQUENCE_TAG {
270 return None;
271 }
272 let (_, rest) = decode_multi_byte_len(&key[1..])?;
273 if *rest.first()? != DER_INTEGER_TAG {
274 return None;
275 }
276 let (len, after_len) = decode_multi_byte_len(&rest[1..])?;
277 after_len
278 .get(..len)?
279 .iter()
280 .position(|&b| b != 0)
281 .map(|leading_zeros| (len - leading_zeros) * 8)
282}
283
284fn try_strip_rsa_prefix(bytes: &[u8]) -> Option<&[u8]> {
288 if *bytes.first()? != DER_SEQUENCE_TAG {
289 return None;
290 }
291
292 let (_, bytes) = decode_multi_byte_len(&bytes[1..])?;
293 if *bytes.first()? != DER_SEQUENCE_TAG {
294 return None;
295 }
296
297 let (byte_len, bytes) = decode_multi_byte_len(&bytes[1..])?;
298 if *bytes.first()? != DER_OBJECT_ID_TAG || byte_len != 13 {
299 return None;
300 }
301
302 let bytes = bytes.get(13..)?;
303 if *bytes.first()? != DER_BIT_STRING_TAG {
304 return None;
305 }
306
307 decode_multi_byte_len(&bytes[1..]).and_then(|(_, bytes)| bytes.get(1..))
308}
309
310fn decode_multi_byte_len(bytes: &[u8]) -> Option<(usize, &[u8])> {
311 if bytes.first()? & 0x80 == 0 {
312 return Some((bytes[0] as usize, &bytes[1..]));
313 }
314
315 let len_len = (bytes[0] & 0x7f) as usize;
316 if bytes.len() < len_len + 1 {
317 return None;
318 }
319
320 let mut len = 0;
321 for i in 0..len_len {
322 len = (len << 8) | bytes[1 + i] as usize;
323 }
324
325 Some((len, &bytes[len_len + 1..]))
326}
327
328const DER_OBJECT_ID_TAG: u8 = 0x06;
329const DER_BIT_STRING_TAG: u8 = 0x03;
330const DER_SEQUENCE_TAG: u8 = 0x30;
331const DER_INTEGER_TAG: u8 = 0x02;
332
333impl VerifyingKey for RsaPublicKey {
334 fn verify<'a>(
335 &self,
336 headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
337 signature: &[u8],
338 canonicalization: Canonicalization,
339 algorithm: Algorithm,
340 ) -> Result<()> {
341 let mut data = Vec::with_capacity(256);
342 canonicalization.canonicalize_headers(headers, &mut data);
343
344 match algorithm {
345 Algorithm::RsaSha256 => UnparsedPublicKey::new(
346 &RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
347 self.key.as_slice(),
348 )
349 .verify(&data, signature)
350 .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
351 Algorithm::RsaSha1 => UnparsedPublicKey::new(
352 &RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
353 self.key.as_slice(),
354 )
355 .verify(&data, signature)
356 .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
357 Algorithm::Ed25519Sha256 | Algorithm::MlDsa44Ed25519Sha512 => {
358 Err(Error::Crypto(CryptoError::IncompatibleAlgorithms))
359 }
360 }
361 }
362
363 fn verify_bytes(&self, input: &[u8], signature: &[u8], algorithm: Algorithm) -> Result<()> {
364 match algorithm {
365 Algorithm::RsaSha256 => UnparsedPublicKey::new(
366 &RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
367 self.key.as_slice(),
368 )
369 .verify(input, signature)
370 .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
371 Algorithm::RsaSha1 => UnparsedPublicKey::new(
372 &RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
373 self.key.as_slice(),
374 )
375 .verify(input, signature)
376 .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
377 Algorithm::Ed25519Sha256 | Algorithm::MlDsa44Ed25519Sha512 => {
378 Err(Error::Crypto(CryptoError::IncompatibleAlgorithms))
379 }
380 }
381 }
382
383 fn public_key_bits(&self) -> usize {
384 rsa_modulus_bits(&self.key).unwrap_or_default()
385 }
386
387 fn heap_size(&self) -> usize {
388 self.key.capacity()
389 }
390}
391
392pub(crate) struct Ed25519PublicKey {
393 inner: UnparsedPublicKey<Vec<u8>>,
394}
395
396impl Ed25519PublicKey {
397 pub(crate) fn verifying_key_from_bytes(
398 bytes: &[u8],
399 ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
400 Ok(Box::new(Self {
401 inner: UnparsedPublicKey::new(&ED25519, bytes.to_vec()),
402 }))
403 }
404}
405
406impl VerifyingKey for Ed25519PublicKey {
407 fn verify<'a>(
408 &self,
409 headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
410 signature: &[u8],
411 canonicalization: Canonicalization,
412 algorithm: Algorithm,
413 ) -> Result<()> {
414 if !matches!(algorithm, Algorithm::Ed25519Sha256) {
415 return Err(Error::Crypto(CryptoError::IncompatibleAlgorithms));
416 }
417
418 let mut hasher = Sha256::hasher();
419 canonicalization.canonicalize_headers(headers, &mut hasher);
420 self.inner
421 .verify(hasher.complete().as_ref(), signature)
422 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))
423 }
424
425 fn verify_bytes(&self, input: &[u8], signature: &[u8], algorithm: Algorithm) -> Result<()> {
426 if !matches!(algorithm, Algorithm::Ed25519Sha256) {
427 return Err(Error::Crypto(CryptoError::IncompatibleAlgorithms));
428 }
429
430 let mut hasher = Sha256::hasher();
431 hasher.write(input);
432 self.inner
433 .verify(hasher.complete().as_ref(), signature)
434 .map_err(|_| Error::Crypto(CryptoError::FailedVerification))
435 }
436
437 fn heap_size(&self) -> usize {
438 self.inner.as_ref().len()
439 }
440}
441
442pub struct MlDsa44Ed25519Key {
450 mldsa: MlDsa44,
451 ed25519: Ed25519KeyPair,
452}
453
454impl MlDsa44Ed25519Key {
455 pub fn generate_pkcs8() -> Result<Vec<u8>> {
464 let mut mldsa = Seed::default();
465 let mut ed25519 = Seed::default();
466 aws_lc_rs::rand::fill(&mut mldsa)
467 .and_then(|()| aws_lc_rs::rand::fill(&mut ed25519))
468 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?;
469 Ok(composite::pkcs8_der(&mldsa, &ed25519))
470 }
471
472 pub fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self> {
480 Self::from_private_key(PrivateKey::from_pkcs8_der(pkcs8_der)?)
481 }
482
483 pub fn from_raw_private_key(raw: &[u8]) -> Result<Self> {
491 Self::from_private_key(PrivateKey::from_raw(raw)?)
492 }
493
494 fn from_private_key(key: PrivateKey<'_>) -> Result<Self> {
495 Ok(Self {
496 mldsa: MlDsa44::from_seed(key.mldsa)
497 .ok_or_else(|| library_error("Invalid ML-DSA-44 seed"))?,
498 ed25519: Ed25519KeyPair::from_seed_unchecked(key.ed25519)
499 .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
500 })
501 }
502
503 pub fn public_key(&self) -> Result<Vec<u8>> {
512 let mldsa = self
513 .mldsa
514 .public_key()
515 .ok_or_else(|| library_error("Cannot export the ML-DSA-44 public key"))?;
516 let mut key = Vec::with_capacity(PUBLIC_KEY_LEN);
517 key.extend_from_slice(&mldsa);
518 key.extend_from_slice(self.ed25519.public_key().as_ref());
519 Ok(key)
520 }
521}
522
523impl SigningKey for MlDsa44Ed25519Key {
524 type Hasher = Sha512;
525
526 fn sign(&self, input: impl Writable) -> Result<Vec<u8>> {
527 let representative = message_representative(input);
528 let mldsa = self
529 .mldsa
530 .sign(&representative, LABEL)
531 .ok_or_else(|| library_error("ML-DSA-44 signing failed"))?;
532 let mut signature = Vec::with_capacity(SIGNATURE_LEN);
533 signature.extend_from_slice(&mldsa);
534 signature.extend_from_slice(self.ed25519.sign(&representative).as_ref());
535 Ok(signature)
536 }
537
538 fn algorithm(&self) -> Algorithm {
539 Algorithm::MlDsa44Ed25519Sha512
540 }
541
542 fn heap_size(&self) -> usize {
543 MLDSA44_PRIVATE_KEY_HEAP_SIZE + ED25519_PRIVATE_KEY_HEAP_SIZE
544 }
545}
546
547pub(crate) struct MlDsa44Ed25519PublicKey {
548 mldsa: MlDsa44,
549 ed25519: UnparsedPublicKey<[u8; ED25519_PUBLIC_KEY_LEN]>,
550}
551
552impl MlDsa44Ed25519PublicKey {
553 pub(crate) fn verifying_key_from_bytes(
554 bytes: &[u8],
555 ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
556 let key = PublicKey::from_bytes(bytes)?;
557 Ok(Box::new(Self {
558 mldsa: MlDsa44::from_public_key(key.mldsa)
559 .ok_or_else(|| library_error("Invalid ML-DSA-44 public key"))?,
560 ed25519: UnparsedPublicKey::new(&ED25519, *key.ed25519),
561 }))
562 }
563}
564
565impl VerifyingKey for MlDsa44Ed25519PublicKey {
566 fn verify<'a>(
567 &self,
568 _: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
569 _: &[u8],
570 _: Canonicalization,
571 _: Algorithm,
572 ) -> Result<()> {
573 Err(Error::Crypto(CryptoError::IncompatibleAlgorithms))
574 }
575
576 fn verify_bytes(&self, input: &[u8], signature: &[u8], algorithm: Algorithm) -> Result<()> {
577 if !matches!(algorithm, Algorithm::MlDsa44Ed25519Sha512) {
578 return Err(Error::Crypto(CryptoError::IncompatibleAlgorithms));
579 }
580 let signature = composite::Signature::from_bytes(signature)
581 .ok_or(Error::Crypto(CryptoError::FailedVerification))?;
582 let representative = message_representative(input);
583 if self.mldsa.verify(&representative, LABEL, signature.mldsa)
584 && self
585 .ed25519
586 .verify(&representative, signature.ed25519)
587 .is_ok()
588 {
589 Ok(())
590 } else {
591 Err(Error::Crypto(CryptoError::FailedVerification))
592 }
593 }
594
595 fn heap_size(&self) -> usize {
596 MLDSA44_PUBLIC_KEY_HEAP_SIZE
597 }
598}
599
600impl HashImpl for Sha1 {
601 type Context = Context;
602
603 fn hasher() -> Self::Context {
604 Context::new(&SHA1_FOR_LEGACY_USE_ONLY)
605 }
606}
607
608impl HashImpl for Sha256 {
609 type Context = Context;
610
611 fn hasher() -> Self::Context {
612 Context::new(&SHA256)
613 }
614}
615
616impl HashImpl for Sha512 {
617 type Context = Context;
618
619 fn hasher() -> Self::Context {
620 Context::new(&SHA512)
621 }
622}
623
624impl HashContext for Context {
625 fn complete(self) -> HashOutput {
626 HashOutput::Digest(self.finish())
627 }
628}
629
630impl Writer for Context {
631 fn write(&mut self, data: &[u8]) {
632 self.update(data);
633 }
634}
635
636#[cfg(test)]
637mod tests {
638 use super::*;
639
640 #[test]
641 fn from_key_der_pkcs1() {
642 let key_der = PrivateKeyDer::from_pem_slice(PKCS1_PEM.as_bytes()).unwrap();
643 assert!(matches!(key_der, PrivateKeyDer::Pkcs1(_)));
644 RsaKey::<Sha256>::from_key_der(key_der).unwrap();
645 }
646
647 #[test]
648 fn from_key_der_pkcs8() {
649 let key_der = PrivateKeyDer::from_pem_slice(PKCS8_PEM.as_bytes()).unwrap();
650 assert!(matches!(key_der, PrivateKeyDer::Pkcs8(_)));
651 RsaKey::<Sha256>::from_key_der(key_der).unwrap();
652 }
653
654 const PKCS1_PEM: &str = r#"-----BEGIN RSA PRIVATE KEY-----
655MIIEoAIBAAKCAQEAplSshLNG7gYj7LckWBQ5Gg1mrFGj2soo3VuMKSbvfR6tMrnj
656khKUSl3TWQyKdkuOOf4EzAyxhJdq/hWGvMdwfwH2q4UzjjcaRHDP54oBH6WHxyAn
657UUkJTFfJo2i8jFE/um09igLr5sEaKMiHgjQIdUScuQRGqKhqS9e4tPpTnfP4ayvM
658zVvD1ptUnaV4O9+GkpEwx/vLVXItMO2KNXXKADYBuWcY9g+Dlpp637radmLJjnvj
659bCJipWjuVzUEQvIvf3x1dZ4b899Bycp4uScmdz5brfxkhLaA9vchnmr+F7aAuwwK
660N5X2Ep6n5d1M0XjA02Z9Zi2W4NkZiNBBmb/f6QIDAQABAoIBAAPzPANNGv4L98jx
661+C3o/F/YbyE1sXmV9lP8I1nr1+FbETvEleQSHGL1aPpIVbZ6/gugXdP3E4qFqmUS
662ik1hQtRFWJVuDPwk5ghiPHxwIYLd+cRFHiHsT96isWzNJTiDinWpN/5XKkE5QfTe
663KaJc4tGJebEG1LhsgtUTxbTImCPxYvKUItDlApOusVvhARjqCnXunNEu5iDiADHH
664Wsv3eSPdWkdF5Jjgt/bI4I9XmagX3e1z6ZQiGvdBwCc8ccwkU6yTswXgWCPqyw/t
665lbTFqE19lEoHGTYYElKaHUo9hCmI3HZS69ShYKG7dMT9dVLhzRlNx7AzZcYWh8Mx
666Ptc8OY0CgYEA1LJe5EpfJ/XvzbiVtNiq07CGhlQj62DAH+XpyqtWHHrUNgMbnBZS
66729had9h2NyfIFDIZAKPGWRuSB6PSyDR6w5Sugh5nRoXshzaFr1pAHmo18s+QELjj
668XyccwivxRXurwmdDL5Bx0YCKII4LJyE3CBlJzq0/wOxvi+iKDRG+TIUCgYEAyDG8
669DXk+E6f9Vd4phaN3sLVDd228U/NNuEr+K74AFHwomgEv//KdK2i/EjFq0zGf31jE
670QMoVbnTDmmzVPfKRDlD3tk5XIz2TDzgGxOYBIWJLUiOlkXxckbLVJBR3NxKn561n
671id7vMR8ik+hAhEp9yZishZr+QrS/4AyHR3ahBRUCgYBYgoGKboh6kJVh/lYOE7vC
672q8rPS2RHJtPMclh/xhznbRWyBEkRAxkn8zhydtl6ykswXEibQ4veuOJj24BzX6NW
673kCCudQh1CHYNLlsjRWM5ROl+SXGiA85aYmRNSQv15ijrlR0YRfuXOu4/7dwmRGQq
674MpvMLbxCBCHHDtWj6qZOIQKBgF+3F7hBbaKsQP2bGLMicwlzwOwK9W4V9+TTRi7X
675yuYAbtEjHDX9Y5Prot8p7W9IXK3GnR51AEYtYZAl1NancR8tKyJo1lStDfDK0sG1
676TnkNrAF7tZ+XnBK1NB7qAg28x7aHO+e5RRdxUXDyLFaT3wxSCLpgXoy6KrsOgmdy
677mo35An9pYQ3Ik9ghh3PJsQ0r/TywuKIzmSvLJZfI/cuBOFkPDoWCleQGdzyQcxuc
678PSCtw8eXUj/Oc09qo5dRWXQkt5uW8sJB0k5fNnfCDqNReUXavDNXOHq31J5USy5R
6798ts1bmtZtK0oRci6A8PcgWChUvSfFUT5IrQM/x4rxabn8qIK
680-----END RSA PRIVATE KEY-----
681"#;
682
683 const PKCS8_PEM: &str = r#"-----BEGIN PRIVATE KEY-----
684MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXxo5+n7aZ0psn
685dNjs53za9Af657AuG3sVnvWEBf24OvwwWClJ5vN+cWA7V2yIuuVvd40RxX1N4HLX
686QewaUBVw+XlHanskcYA8WTVuMTI6XNY6hIAtU1ETSWAPke5sH6DyrAzxIoC2R+IH
687ejqwjtdWdQ0MNVudqY3BO6mAH+zYblRzytMmcols+aqYNgZeAYuEie+EiJiTT65v
688y0mG24k0ALF5XLPahxhoUK/xuhjjG/Y/InD8s6C4BksO29bStnyqhMToSGMtUyOT
689PTyh1XgrUB4dlfEnpfX9F/wU8a7ijrD38Qtg935c08Qg9YcwVXzpFHWRw/ZF/auq
690lcazbMaHAgMBAAECggEAOKmhncrfLsHJkLD0jjGz7eOLfO3+q/z3c5QMsSDJoemL
691dD6SiR+m7ZtkQ/EPRVCfE4h3eSU9ZIf+YFylXbuOBd7dZE2oDMfpfu+GQmuU3xKm
692BzPoXP62GbR5D12pGKetokxgEaqX1kZGKuSEKP05uzB9vqj8aAiwev/p4QWBMsw6
6932stumeWMuZortwL9PZpXgzpJPHXDnFdsn3OIINBMFYFdqda8RhL3rWWsbV5nL1oR
694Q2/SMPLc1dQ8ZQKdPmbVhdfnPitVKVEkn8xIiFPWNS3SfYIi+wQj0lWdJbvUUJ1i
6957BIXvnXeeVLyYhekTpE5ZnGeGI4A5lix4PN+GIao8QKBgQDtuPW8BaXWfPHb93Kl
696mWBQNHz0I71p8GL9/+xRpA9SMuUtYS0jJ1whNgcwoSI4cOKo1UsIMDPAPpTU47Ul
6970D+vXr/GyiONL6+IsXAf5xhaQnUWRWKs4G9obadyGkT8aH6y8W+ddKD1JWQKUf4t
698Bmpeim+Ck0I8POhDbNNfThTLwwKBgQDoXZ70Pb6HViZAbzf+rEznNycgG8IqtTSc
699V7YoSMZe17u0AQjE9XZizBrhpz47N6/JvyYTBIh6VPQe880FTnHdUjvbqn8bmLE7
700QEYwvgF5hmHVXlWXUsyKbfMH5Dp8Uy74FV2VTd1hJ7UMSke7LQT41Hgyaz32x7Lm
701r0P63fgh7QKBgQDMrnCGz6YWo8XrS4efJgxTgp4D57HzQVM6t9xV/xhiAghppj4j
702AoTE46wVJug8CJZgICZWiopEgJ3NH7KdOE1dRguBshIiQmi1HXIZRfUl4grGfj+T
7038jp6g8+k4xF68s4EbPVZcU4VRXh5mldrlRaJCFEy8HAbRaYGR/FHIget2QKBgGd/
704o9h4VBAmAD29DDzkdBCc0VGM66xoL/nfW6SP3cPK5bFksIpCJywUa3jNLHvl7ue2
705u3fHEh8jDeVnhI9zhGYnRcAvLhSVq4OPunPlffSqNZN7RDZ1y+Nw28pNDvvndUlN
706AvUIzK2EqTDDOTYW9Fr9EFisydnM01PLB0WLbwV1AoGAGmaWcbNfPyPnJU1nIHGG
707fPlEpGn+3Oxr1ja02FPwexk/bg6CRVIqP2x7RtR1cH9fOqiDOoIqyfKswuZkwVj3
708EMeos/WHHrw+UzXem+IswmwG9rnUBMlMRCkJ9GhXk98bqoWeJpMhlj1L+oBQ3Spj
709j8T1spkdY4jj3CvmzQ0ha0U=
710-----END PRIVATE KEY-----
711"#;
712}