Skip to content

Commit

Permalink
feat(key): import private rsa keys into openssl
Browse files Browse the repository at this point in the history
Former-commit-id: d555289
  • Loading branch information
dignifiedquire committed Jul 5, 2018
1 parent 4a0ac3b commit 11ce8e4
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 114 deletions.
56 changes: 39 additions & 17 deletions src/composed/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::io::Read;
// TODO: rename armor parser to dearmor

/// Represents a Public PGP key.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq)]
pub struct PublicKey {
pub primary_key: types::key::PublicKey,
pub revocation_signatures: Vec<types::Signature>,
Expand Down Expand Up @@ -45,7 +45,7 @@ impl PublicKey {
}

/// Represents a Public PGP SubKey.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq)]
pub struct PublicSubKey {
pub key: types::key::PublicKey,
pub signatures: Vec<types::Signature>,
Expand All @@ -58,7 +58,7 @@ impl PublicSubKey {
}

/// Represents a Private PGP key.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq)]
pub struct PrivateKey {
pub primary_key: types::key::PrivateKey,
pub revocation_signatures: Vec<types::Signature>,
Expand Down Expand Up @@ -94,7 +94,7 @@ impl PrivateKey {
}

/// Represents a composed private PGP SubKey.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq)]
pub struct PrivateSubKey {
pub key: types::key::PrivateKey,
pub signatures: Vec<types::Signature>,
Expand Down Expand Up @@ -152,14 +152,17 @@ pub trait Key: Sized {
mod tests {
use super::*;
use chrono::{DateTime, Utc};
use openssl::bn::BigNum;
use openssl::rsa::Padding;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use packet::types::key;
use packet::types::{
CompressionAlgorithm, HashAlgorithm, KeyVersion, PublicKeyAlgorithm, Signature,
SignatureType, SignatureVersion, Subpacket, SymmetricKeyAlgorithm, User, UserAttributeType,
};
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

fn read_file(path: PathBuf) -> File {
// Open the path in read-only mode, returns `io::Result<File>`
Expand Down Expand Up @@ -261,15 +264,31 @@ mod tests {

pkey.unlock(
|| "",
|priv_params| {
match priv_params {
types::key::PrivateParams::RSA { d, p, q, u } => {
assert_eq!(d.len(), 256); // 2044 bits
assert_eq!(p.len(), 1024 / 8);
assert_eq!(q.len(), 1024 / 8);
assert_eq!(u.len(), 1024 / 8);
|unlocked_key| {
match unlocked_key {
types::key::PrivateKeyRepr::RSA(k) => {
assert_eq!(k.d().num_bits(), 2044);
assert_eq!(k.p().unwrap().num_bits(), 1024);
assert_eq!(k.q().unwrap().num_bits(), 1024);

// test basic encrypt decrypt
let plaintext = vec![2u8; 256];
let mut ciphertext = vec![0u8; 256];

k.public_encrypt(
plaintext.as_slice(),
ciphertext.as_mut_slice(),
Padding::NONE,
).unwrap();
let mut new_plaintext = vec![0u8; 256];
k.private_decrypt(
ciphertext.as_slice(),
new_plaintext.as_mut_slice(),
Padding::NONE,
).unwrap();
assert_eq!(plaintext, new_plaintext);
}
_ => panic!("unexpected params type {:?}", priv_params),
_ => panic!("unexpected params type {:?}", unlocked_key),
}
Ok(())
},
Expand All @@ -284,7 +303,7 @@ mod tests {

// assert_eq!(key.primary_key.fingerprint(), "56c65c513a0d1b9cff532d784c073ae0c8445c0c");

let primary_n = hex!("a5 4c fa 91 42 fb 75 26 53 22 05 5b 11 f7 50 f4 9a f3 7b 64 c6 7a d8 30 ed 74 43 d6 c2 04 77 b0 49 2e e9 09 0e 4c b8 b0 c2 c5 d4 9e 87 df f5 ac 80 1b 1a aa db 31 9e ee 9d 3d 29 b2 5b d9 aa 63 4b 12 6c 0e 5d a4 e6 6b 41 4e 9d bd de 5d ea 0e 38 c5 bf e7 e5 f7 fd b9 f4 c1 b1 f3 9e d8 92 dd 4e 08 73 a0 df 66 ff 46 fd 92 36 d2 91 c2 76 ce 69 fb 97 2f 5e f2 47 46 b6 79 4a 0f 70 e0 69 46 67 b9 de 57 35 33 30 c7 32 73 3c c6 d5 f2 4c d7 72 c5 c7 d5 bd b7 7d c0 a5 b6 e9 d3 ee 03 72 14 67 78 cd a6 14 49 76 e3 30 66 fc 57 bf b5 15 ef 39 7b 3a a8 82 c0 bd e0 2d 19 f7 a3 2d f7 b1 19 5c b0 f3 2e 6e 74 55 ac 19 9f a4 34 35 5f 0f a4 32 30 e5 23 7e 9a 6e 0f f6 ad 5b 21 b4 d8 92 c6 fc 38 42 78 8b a4 8b 02 0e e8 5e dd 13 5c ff 28 08 78 0e 83 4b 5d 94 cc 2c 2b 5f a7 47 16 7a 20 81 45 89 d7 f0 30 ee 9f 8a 66 97 37 bd b0 63 e6 b0 b8 8a b0 fd 74 54 c0 3f 69 67 8a 1d d9 94 42 cf d0 bf 62 0b c5 b6 89 6c d6 e2 b5 1f de cf 54 c7 e6 36 8c 11 c7 0f 30 24 44 ec 9d 5a 17 ce aa cb 4a 9a c3 c3 7d b3 47 8f 8f b0 4a 67 9f 09 57 a3 69 7e 8d 90 15 20 08 92 7c 75 1b 34 16 0c 72 e7 57 ef c8 50 53 dd 86 73 89 31 fd 35 1c f1 34 26 6e 43 6e fd 64 a1 4b 35 86 90 40 10 80 82 84 7f 7f 52 15 62 8e 7f 66 51 38 09 ae 0f 66 ea 73 d0 1f 5f d9 65 14 2c db 78 60 27 6d 4c 20 fa f7 16 c4 0a e0 63 2d 3b 18 01 37 43 8c b9 52 57 32 76 07 03 8f b3 b8 2f 76 55 6e 8d d1 86 b7 7c 2f 51 b0 bf dd 75 52 f1 68 f2 c4 eb 90 84 4f dc 05 cf 23 9a 57 69 02 25 90 33 99 78 3a d3 73 68 91 ed b8 77 45 a1 18 0e 04 74 15 26 38 40 45 c2 de 03 c4 63 c4 3b 27 d5 ab 7f fd 6d 0e cc cc 24 9f").to_vec();
let primary_n = BigNum::from_slice(hex!("a5 4c fa 91 42 fb 75 26 53 22 05 5b 11 f7 50 f4 9a f3 7b 64 c6 7a d8 30 ed 74 43 d6 c2 04 77 b0 49 2e e9 09 0e 4c b8 b0 c2 c5 d4 9e 87 df f5 ac 80 1b 1a aa db 31 9e ee 9d 3d 29 b2 5b d9 aa 63 4b 12 6c 0e 5d a4 e6 6b 41 4e 9d bd de 5d ea 0e 38 c5 bf e7 e5 f7 fd b9 f4 c1 b1 f3 9e d8 92 dd 4e 08 73 a0 df 66 ff 46 fd 92 36 d2 91 c2 76 ce 69 fb 97 2f 5e f2 47 46 b6 79 4a 0f 70 e0 69 46 67 b9 de 57 35 33 30 c7 32 73 3c c6 d5 f2 4c d7 72 c5 c7 d5 bd b7 7d c0 a5 b6 e9 d3 ee 03 72 14 67 78 cd a6 14 49 76 e3 30 66 fc 57 bf b5 15 ef 39 7b 3a a8 82 c0 bd e0 2d 19 f7 a3 2d f7 b1 19 5c b0 f3 2e 6e 74 55 ac 19 9f a4 34 35 5f 0f a4 32 30 e5 23 7e 9a 6e 0f f6 ad 5b 21 b4 d8 92 c6 fc 38 42 78 8b a4 8b 02 0e e8 5e dd 13 5c ff 28 08 78 0e 83 4b 5d 94 cc 2c 2b 5f a7 47 16 7a 20 81 45 89 d7 f0 30 ee 9f 8a 66 97 37 bd b0 63 e6 b0 b8 8a b0 fd 74 54 c0 3f 69 67 8a 1d d9 94 42 cf d0 bf 62 0b c5 b6 89 6c d6 e2 b5 1f de cf 54 c7 e6 36 8c 11 c7 0f 30 24 44 ec 9d 5a 17 ce aa cb 4a 9a c3 c3 7d b3 47 8f 8f b0 4a 67 9f 09 57 a3 69 7e 8d 90 15 20 08 92 7c 75 1b 34 16 0c 72 e7 57 ef c8 50 53 dd 86 73 89 31 fd 35 1c f1 34 26 6e 43 6e fd 64 a1 4b 35 86 90 40 10 80 82 84 7f 7f 52 15 62 8e 7f 66 51 38 09 ae 0f 66 ea 73 d0 1f 5f d9 65 14 2c db 78 60 27 6d 4c 20 fa f7 16 c4 0a e0 63 2d 3b 18 01 37 43 8c b9 52 57 32 76 07 03 8f b3 b8 2f 76 55 6e 8d d1 86 b7 7c 2f 51 b0 bf dd 75 52 f1 68 f2 c4 eb 90 84 4f dc 05 cf 23 9a 57 69 02 25 90 33 99 78 3a d3 73 68 91 ed b8 77 45 a1 18 0e 04 74 15 26 38 40 45 c2 de 03 c4 63 c4 3b 27 d5 ab 7f fd 6d 0e cc cc 24 9f").to_vec().as_slice()).unwrap();

let pk = key.primary_key;
assert_eq!(pk.version(), &KeyVersion::V4);
Expand All @@ -293,7 +312,10 @@ mod tests {
match pk.public_params() {
key::PublicParams::RSA { n, e } => {
assert_eq!(n, &primary_n);
assert_eq!(e, &vec![1u8, 0u8, 1u8]);
assert_eq!(
e,
&BigNum::from_slice(vec![1u8, 0u8, 1u8].as_slice()).unwrap()
);
}
_ => panic!("wrong public params: {:?}", pk.public_params()),
}
Expand Down
2 changes: 1 addition & 1 deletion src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl Error {
Error::RequestedSizeTooLarge => 6,
Error::NoKey => 7,
Error::MultipleKeys => 8,
Error::OpenSSLError(ErrorStack) => 9,
Error::OpenSSLError(_) => 9,
}
}
}
Expand Down
72 changes: 34 additions & 38 deletions src/packet/tags/privkey.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use enum_primitive::FromPrimitive;
use nom::{be_u8, be_u16, be_u32, self};
use openssl::bn::BigNum;

use packet::types::{KeyVersion, PublicKeyAlgorithm, SymmetricKeyAlgorithm, StringToKeyType};
use packet::types::ecc_curve::ecc_curve_from_oid;
use packet::types::key::*;
use composed;
use util::{mpi, rest_len};
use util::{mpi_big, rest_len};

// Ref: https://tools.ietf.org/html/rfc6637#section-9
named!(ecdsa<(PublicParams, EncryptedPrivateParams)>, do_parse!(
Expand All @@ -14,12 +15,8 @@ named!(ecdsa<(PublicParams, EncryptedPrivateParams)>, do_parse!(
// octets representing a curve OID
>> curve: map_opt!(take!(len), ecc_curve_from_oid)
// MPI of an EC point representing a public key
>> p: mpi
>> (PublicParams::ECDSA {
curve,
p: p.to_vec()
},
EncryptedPrivateParams::new_plaintext(vec![], vec![]))
>> p: mpi_big
>> (PublicParams::ECDSA { curve, p }, EncryptedPrivateParams::new_plaintext(vec![], vec![]))
));

// Ref: https://tools.ietf.org/html/rfc6637#section-9
Expand All @@ -29,7 +26,7 @@ named!(ecdh<(PublicParams, EncryptedPrivateParams)>, do_parse!(
// octets representing a curve OID
>> curve: map_opt!(take!(len), ecc_curve_from_oid)
// MPI of an EC point representing a public key
>> p: mpi
>> p: mpi_big
// a one-octet size of the following fields
>> _len2: be_u8
// a one-octet value 01, reserved for future extensions
Expand All @@ -40,46 +37,45 @@ named!(ecdh<(PublicParams, EncryptedPrivateParams)>, do_parse!(
// the symmetric key used for the message encryption
>> alg_sym: take!(1)
>> (PublicParams::ECDH {
curve, p:
p.to_vec(),
hash: hash[0],
alg_sym: alg_sym[0]
},
EncryptedPrivateParams::new_plaintext(vec![], vec![]))
curve,
p,
hash: hash[0],
alg_sym: alg_sym[0]
}, EncryptedPrivateParams::new_plaintext(vec![], vec![]))
));

named!(elgamal<(PublicParams, EncryptedPrivateParams)>, do_parse!(
// MPI of Elgamal prime p
p: mpi
p: mpi_big
// MPI of Elgamal group generator g
>> g: mpi
>> g: mpi_big
// MPI of Elgamal public key value y (= g**x mod p where x is secret)
>> y: mpi
>> y: mpi_big
>> (PublicParams::Elgamal {
p: p.to_vec(),
g: g.to_vec(),
y: y.to_vec()
p,
g,
y,
},
EncryptedPrivateParams::new_plaintext(vec![], vec![]))
));

named!(dsa<(PublicParams, EncryptedPrivateParams)>, do_parse!(
p: mpi
>> q: mpi
>> g: mpi
>> y: mpi
p: mpi_big
>> q: mpi_big
>> g: mpi_big
>> y: mpi_big
>> (PublicParams::DSA {
p: p.to_vec(),
q: q.to_vec(),
g: g.to_vec(),
y: y.to_vec()
p,
q,
g,
y,
},
EncryptedPrivateParams::new_plaintext(vec![], vec![]))
));

named!(rsa<(PublicParams, EncryptedPrivateParams)>, do_parse!(
n: mpi
>> e: mpi
n: mpi_big
>> e: mpi_big
>> s2k_typ: be_u8
>> enc_params: switch!(value!(s2k_typ),
// 0 is no encryption
Expand Down Expand Up @@ -110,8 +106,8 @@ named!(rsa<(PublicParams, EncryptedPrivateParams)>, do_parse!(
>> data: take!(data_len)
>> checksum: take!(checksum_len)
>> (PublicParams::RSA {
n: n.to_vec(),
e: e.to_vec()
n,
e,
},
EncryptedPrivateParams {
data: data.to_vec(),
Expand Down Expand Up @@ -172,11 +168,11 @@ impl composed::key::PrivateKey {
}

/// Parse the decrpyted private params of an RSA private key.
named!(pub rsa_private_params<(Vec<u8>, Vec<u8>,Vec<u8>, Vec<u8>)>, do_parse!(
d: mpi
>> p: mpi
>> q: mpi
>> u: mpi
>> (d.to_vec(), p.to_vec(), q.to_vec(), u.to_vec())
named!(pub rsa_private_params<(BigNum, BigNum,BigNum, BigNum)>, do_parse!(
d: mpi_big
>> p: mpi_big
>> q: mpi_big
>> u: mpi_big
>> (d, p, q, u)
));

34 changes: 17 additions & 17 deletions src/packet/tags/pubkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use packet::types::{KeyVersion, PublicKeyAlgorithm};
use packet::types::ecc_curve::ecc_curve_from_oid;
use packet::types::key::*;
use composed;
use util::mpi;
use util::mpi_big;

// Ref: https://tools.ietf.org/html/rfc6637#section-9
named!(ecdsa<PublicParams>, do_parse!(
Expand All @@ -14,8 +14,8 @@ named!(ecdsa<PublicParams>, do_parse!(
// octets representing a curve OID
>> curve: map_opt!(take!(len), ecc_curve_from_oid)
// MPI of an EC point representing a public key
>> p: mpi
>> (PublicParams::ECDSA{ curve, p: p.to_vec()})
>> p: mpi_big
>> (PublicParams::ECDSA{ curve, p})
));

// Ref: https://tools.ietf.org/html/rfc6637#section-9
Expand All @@ -25,7 +25,7 @@ named!(ecdh<PublicParams>, do_parse!(
// octets representing a curve OID
>> curve: map_opt!(take!(len), ecc_curve_from_oid)
// MPI of an EC point representing a public key
>> p: mpi
>> p: mpi_big
// a one-octet size of the following fields
>> _len2: be_u8
// a one-octet value 01, reserved for future extensions
Expand All @@ -35,31 +35,31 @@ named!(ecdh<PublicParams>, do_parse!(
// a one-octet algorithm ID for the symmetric algorithm used to wrap
// the symmetric key used for the message encryption
>> alg_sym: take!(1)
>> (PublicParams::ECDH{curve, p: p.to_vec(), hash: hash[0], alg_sym: alg_sym[0]})
>> (PublicParams::ECDH{curve, p, hash: hash[0], alg_sym: alg_sym[0]})
));

named!(elgamal<PublicParams>, do_parse!(
// MPI of Elgamal prime p
p: mpi
p: mpi_big
// MPI of Elgamal group generator g
>> g: mpi
>> g: mpi_big
// MPI of Elgamal public key value y (= g**x mod p where x is secret)
>> y: mpi
>> (PublicParams::Elgamal{p: p.to_vec(), g: g.to_vec(), y: y.to_vec()})
>> y: mpi_big
>> (PublicParams::Elgamal{ p, g, y })
));

named!(dsa<PublicParams>, do_parse!(
p: mpi
>> q: mpi
>> g: mpi
>> y: mpi
>> (PublicParams::DSA{p: p.to_vec(), q: q.to_vec(), g: g.to_vec(), y: y.to_vec()})
p: mpi_big
>> q: mpi_big
>> g: mpi_big
>> y: mpi_big
>> (PublicParams::DSA { p, q, g, y })
));

named!(rsa<PublicParams>, do_parse!(
n: mpi
>> e: mpi
>> (PublicParams::RSA{n: n.to_vec(), e: e.to_vec()})
n: mpi_big
>> e: mpi_big
>> (PublicParams::RSA { n, e })
));


Expand Down
Loading

0 comments on commit 11ce8e4

Please sign in to comment.