summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openpgp/src/crypto/hash.rs3
-rw-r--r--openpgp/src/message/mod.rs8
-rw-r--r--openpgp/src/packet/key.rs125
-rw-r--r--openpgp/src/packet/mod.rs80
-rw-r--r--openpgp/src/packet/pkesk.rs7
-rw-r--r--openpgp/src/packet/prelude.rs1
-rw-r--r--openpgp/src/packet/signature/mod.rs9
-rw-r--r--openpgp/src/packet/signature/subpacket.rs3
-rw-r--r--openpgp/src/parse/key.rs4
-rw-r--r--openpgp/src/parse/parse.rs42
-rw-r--r--openpgp/src/serialize/mod.rs31
-rw-r--r--openpgp/src/tpk/builder.rs9
-rw-r--r--openpgp/src/tpk/mod.rs4
-rw-r--r--openpgp/src/tsk.rs4
14 files changed, 227 insertions, 103 deletions
diff --git a/openpgp/src/crypto/hash.rs b/openpgp/src/crypto/hash.rs
index f6861957..674245ba 100644
--- a/openpgp/src/crypto/hash.rs
+++ b/openpgp/src/crypto/hash.rs
@@ -4,6 +4,7 @@ use HashAlgorithm;
use packet::UserID;
use packet::UserAttribute;
use packet::Key;
+use packet::key::Key4;
use packet::Signature;
use packet::signature::{self, Signature4};
use Error;
@@ -175,7 +176,7 @@ impl Hash for UserAttribute {
}
}
-impl Hash for Key {
+impl Hash for Key4 {
/// Update the Hash with a hash of the key.
fn hash<H: nettle::Hash + Write>(&self, hash: &mut H) {
// We hash 8 bytes plus the MPIs. But, the len doesn't
diff --git a/openpgp/src/message/mod.rs b/openpgp/src/message/mod.rs
index 3ea99194..51a4f84c 100644
--- a/openpgp/src/message/mod.rs
+++ b/openpgp/src/message/mod.rs
@@ -748,7 +748,9 @@ mod tests {
lit.set_body(b"data".to_vec());
let hash = ::constants::HashAlgorithm::SHA512;
- let key = ::packet::Key::generate_ecc(true, ::constants::Curve::Ed25519).unwrap();
+ let key: Key =
+ ::packet::key::Key4::generate_ecc(true, ::constants::Curve::Ed25519)
+ .unwrap().into();
let sec =
if let Some(SecretKey::Unencrypted { ref mpis }) = key.secret() {
mpis.clone()
@@ -864,7 +866,9 @@ mod tests {
lit.set_body(b"data".to_vec());
let hash = ::constants::HashAlgorithm::SHA512;
- let key = ::packet::Key::generate_ecc(true, ::constants::Curve::Ed25519).unwrap();
+ let key: Key =
+ ::packet::key::Key4::generate_ecc(true, ::constants::Curve::Ed25519)
+ .unwrap().into();
let sec =
if let Some(SecretKey::Unencrypted { ref mpis }) = key.secret() {
mpis.clone()
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs
index 862eba6f..bf76ce5b 100644
--- a/openpgp/src/packet/key.rs
+++ b/openpgp/src/packet/key.rs
@@ -25,11 +25,9 @@ use crypto::Password;
///
/// [Section 5.5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.5
#[derive(PartialEq, Eq, Hash, Clone)]
-pub struct Key {
+pub struct Key4 {
/// CTB packet header fields.
pub(crate) common: packet::Common,
- /// Version of the key packet. Must be 4.
- version: u8,
/// When the key was created.
creation_time: time::Tm,
/// Public key algorithm of this signature.
@@ -41,11 +39,10 @@ pub struct Key {
}
-impl fmt::Debug for Key {
+impl fmt::Debug for Key4 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("Key")
+ f.debug_struct("Key4")
.field("fingerprint", &self.fingerprint())
- .field("version", &self.version)
.field("creation_time", &format!("{}", self.creation_time.rfc3339()))
.field("pk_algo", &self.pk_algo)
.field("mpis", &self.mpis)
@@ -54,17 +51,17 @@ impl fmt::Debug for Key {
}
}
-impl fmt::Display for Key {
+impl fmt::Display for Key4 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.fingerprint())
}
}
-impl Key {
+impl Key4 {
/// Compares the public bits of two keys.
///
- /// This returns Ordering::Equal if the public MPIs, version,
- /// creation time and algorithm of the two `Key`s match. This
+ /// This returns Ordering::Equal if the public MPIs,
+ /// creation time and algorithm of the two `Key4`s match. This
/// does not consider the packet's encoding, packet's tag or the
/// secret key material.
pub fn public_cmp(a: &Self, b: &Self) -> Ordering {
@@ -73,11 +70,6 @@ impl Key {
o => return o,
}
- match a.version.cmp(&b.version) {
- Ordering::Equal => (),
- o => return o,
- }
-
match a.creation_time.cmp(&b.creation_time) {
Ordering::Equal => (),
o => return o,
@@ -87,15 +79,14 @@ impl Key {
}
}
-impl Key {
+impl Key4 {
/// Creates a new OpenPGP key packet.
pub fn new(creation_time: time::Tm, pk_algo: PublicKeyAlgorithm,
mpis: mpis::PublicKey, secret: Option<SecretKey>)
- -> Result<Key>
+ -> Result<Self>
{
- Ok(Key {
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: creation_time,
pk_algo: pk_algo,
mpis: mpis,
@@ -116,9 +107,8 @@ impl Key {
let mut point = Vec::from(public_key);
point.insert(0, 0x40);
- Ok(Key{
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: ctime.into().unwrap_or(time::now()),
pk_algo: PublicKeyAlgorithm::ECDH,
mpis: mpis::PublicKey::ECDH{
@@ -149,9 +139,8 @@ impl Key {
let mut private_key = Vec::from(private_key);
private_key.reverse();
- Ok(Key{
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: ctime.into().unwrap_or(time::now()),
pk_algo: PublicKeyAlgorithm::ECDH,
mpis: mpis::PublicKey::ECDH{
@@ -179,9 +168,8 @@ impl Key {
let mut point = Vec::from(public_key);
point.insert(0, 0x40);
- Ok(Key{
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: ctime.into().unwrap_or(time::now()),
pk_algo: PublicKeyAlgorithm::EdDSA,
mpis: mpis::PublicKey::EdDSA{
@@ -205,9 +193,8 @@ impl Key {
let mut public_key = [0x40u8; ED25519_KEY_SIZE + 1];
ed25519::public_key(&mut public_key[1..], private_key).unwrap();
- Ok(Key{
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: ctime.into().unwrap_or(time::now()),
pk_algo: PublicKeyAlgorithm::EdDSA,
mpis: mpis::PublicKey::EdDSA{
@@ -230,9 +217,8 @@ impl Key {
pub fn import_public_rsa<T>(e: &[u8], n: &[u8], ctime: T)
-> Result<Self> where T: Into<Option<time::Tm>>
{
- Ok(Key{
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: ctime.into().unwrap_or(time::now()),
pk_algo: PublicKeyAlgorithm::RSAEncryptSign,
mpis: mpis::PublicKey::RSA{
@@ -257,9 +243,8 @@ impl Key {
let key = sec.public_key()?;
let (a, b, c) = sec.as_rfc4880();
- Ok(Key{
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: ctime.into().unwrap_or(time::now()),
pk_algo: PublicKeyAlgorithm::RSAEncryptSign,
mpis: mpis::PublicKey::RSA{
@@ -299,9 +284,8 @@ impl Key {
mpis: private_mpis
});
- Ok(Key {
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: time::now().canonicalize(),
pk_algo: PublicKeyAlgorithm::RSAEncryptSign,
mpis: public_mpis,
@@ -459,9 +443,8 @@ impl Key {
}
};
- Ok(Key {
+ Ok(Key4 {
common: Default::default(),
- version: 4,
creation_time: time::now().canonicalize(),
pk_algo: pk_algo,
mpis: mpis,
@@ -469,11 +452,6 @@ impl Key {
})
}
- /// Gets the key packet's version field.
- pub fn version(&self) -> u8 {
- self.version
- }
-
/// Gets the key packet's creation time field.
pub fn creation_time(&self) -> &time::Tm {
&self.creation_time
@@ -531,10 +509,10 @@ impl Key {
/// Convert the `Key` struct to a `Packet`.
pub fn into_packet(self, tag: Tag) -> Result<Packet> {
match tag {
- Tag::PublicKey => Ok(Packet::PublicKey(self)),
- Tag::PublicSubkey => Ok(Packet::PublicSubkey(self)),
- Tag::SecretKey => Ok(Packet::SecretKey(self)),
- Tag::SecretSubkey => Ok(Packet::SecretSubkey(self)),
+ Tag::PublicKey => Ok(Packet::PublicKey(self.into())),
+ Tag::PublicSubkey => Ok(Packet::PublicSubkey(self.into())),
+ Tag::SecretKey => Ok(Packet::SecretKey(self.into())),
+ Tag::SecretSubkey => Ok(Packet::SecretSubkey(self.into())),
_ => Err(Error::InvalidArgument(
format!("Expected Tag::PublicKey, Tag::PublicSubkey, \
Tag::SecretKey, or Tag::SecretSubkey. \
@@ -561,7 +539,13 @@ impl Key {
"no secret key".into()).into()),
};
- KeyPair::new(self, secret)
+ KeyPair::new(self.into(), secret)
+ }
+}
+
+impl From<Key4> for super::Key {
+ fn from(p: Key4) -> Self {
+ super::Key::V4(p)
}
}
@@ -684,6 +668,7 @@ impl SecretKey {
#[cfg(test)]
mod tests {
use packet::Tag;
+ use packet::Key;
use TPK;
use packet::pkesk::PKESK3;
use packet::key::SecretKey;
@@ -703,10 +688,11 @@ mod tests {
let mut tpk = TPK::from_file(
path_to("testy-new-encrypted-with-123.pgp")).unwrap();
let pair = tpk.primary_mut();
+ let pk_algo = pair.pk_algo();
let secret = pair.secret.as_mut().unwrap();
assert!(secret.is_encrypted());
- secret.decrypt_in_place(pair.pk_algo, &"123".into()).unwrap();
+ secret.decrypt_in_place(pk_algo, &"123".into()).unwrap();
assert!(!secret.is_encrypted());
match secret {
@@ -721,8 +707,8 @@ mod tests {
use constants::Curve::*;
for curve in vec![NistP256, NistP384, NistP521] {
- let sign_key = Key::generate_ecc(true, curve.clone()).unwrap();
- let enc_key = Key::generate_ecc(false, curve).unwrap();
+ let sign_key = Key4::generate_ecc(true, curve.clone()).unwrap();
+ let enc_key = Key4::generate_ecc(false, curve).unwrap();
let sign_clone = sign_key.clone();
let enc_clone = enc_key.clone();
@@ -731,7 +717,7 @@ mod tests {
}
for bits in vec![1024, 2048, 3072, 4096] {
- let key = Key::generate_rsa(bits).unwrap();
+ let key = Key4::generate_rsa(bits).unwrap();
let clone = key.clone();
assert_eq!(key, clone);
}
@@ -742,12 +728,12 @@ mod tests {
use constants::Curve::*;
let keys = vec![NistP256, NistP384, NistP521].into_iter().flat_map(|cv| {
- let sign_key = Key::generate_ecc(true, cv.clone()).unwrap();
- let enc_key = Key::generate_ecc(false, cv).unwrap();
+ let sign_key = Key4::generate_ecc(true, cv.clone()).unwrap();
+ let enc_key = Key4::generate_ecc(false, cv).unwrap();
vec![sign_key, enc_key]
}).chain(vec![1024, 2048, 3072, 4096].into_iter().map(|b| {
- Key::generate_rsa(b).unwrap()
+ Key4::generate_rsa(b).unwrap()
}));
for mut key in keys {
@@ -755,9 +741,10 @@ mod tests {
key.serialize(&mut b, Tag::SecretKey).unwrap();
let pp = PacketPile::from_bytes(&b).unwrap();
- if let Some(Packet::SecretKey(ref parsed_key)) = pp.path_ref(&[0]) {
+ if let Some(Packet::SecretKey(Key::V4(ref parsed_key))) =
+ pp.path_ref(&[0])
+ {
assert_eq!(key.common, parsed_key.common);
- assert_eq!(key.version, parsed_key.version);
assert_eq!(key.creation_time, parsed_key.creation_time);
assert_eq!(key.pk_algo, parsed_key.pk_algo);
assert_eq!(key.mpis, parsed_key.mpis);
@@ -772,7 +759,9 @@ mod tests {
key.serialize(&mut b, Tag::PublicKey).unwrap();
let pp = PacketPile::from_bytes(&b).unwrap();
- if let Some(Packet::PublicKey(ref parsed_key)) = pp.path_ref(&[0]) {
+ if let Some(Packet::PublicKey(Key::V4(ref parsed_key))) =
+ pp.path_ref(&[0])
+ {
assert!(parsed_key.secret().is_none());
key.set_secret(None);
@@ -790,12 +779,13 @@ mod tests {
use constants::Curve::*;
let keys = vec![NistP256, NistP384, NistP521].into_iter().map(|cv| {
- Key::generate_ecc(false, cv).unwrap()
+ Key4::generate_ecc(false, cv).unwrap()
}).chain(vec![1024, 2048, 3072, 4096].into_iter().map(|b| {
- Key::generate_rsa(b).unwrap()
+ Key4::generate_rsa(b).unwrap()
}));
- for mut key in keys {
+ for key in keys.into_iter() {
+ let key = Key::from(key);
let secret =
if let Some(SecretKey::Unencrypted {
ref mpis,
@@ -822,9 +812,9 @@ mod tests {
use constants::Curve::*;
let keys = vec![NistP256, NistP384, NistP521].into_iter().map(|cv| {
- Key::generate_ecc(false, cv).unwrap()
+ Key4::generate_ecc(false, cv).unwrap()
}).chain(vec![1024, 2048, 3072, 4096].into_iter().map(|b| {
- Key::generate_rsa(b).unwrap()
+ Key4::generate_rsa(b).unwrap()
}));
for key in keys {
@@ -854,7 +844,10 @@ mod tests {
// X25519 key
let ctime = at(Timespec::new(0x5c487129,0));
let public = b"\xed\x59\x0a\x15\x08\x95\xe9\x92\xd2\x2c\x14\x01\xb3\xe9\x3b\x7f\xff\xe6\x6f\x22\x65\xec\x69\xd9\xb8\xda\x24\x2c\x64\x84\x44\x11";
- let key = Key::import_public_cv25519(&public[..], HashAlgorithm::SHA256, SymmetricAlgorithm::AES128, ctime).unwrap();
+ let key = Key4::import_public_cv25519(&public[..],
+ HashAlgorithm::SHA256,
+ SymmetricAlgorithm::AES128,
+ ctime).unwrap().into();
// PKESK
let eph_pubkey = MPI::new(&b"\x40\xda\x1c\x69\xc4\xe3\xb6\x9c\x6e\xd4\xc6\x69\x6c\x89\xc7\x09\xe9\xf8\x6a\xf1\xe3\x8d\xb6\xaa\xb5\xf7\x29\xae\xa6\xe7\xdd\xfe\x38"[..]);
@@ -884,7 +877,10 @@ mod tests {
let ctime = at(Timespec::new(0x5c487129,0));
let public = b"\xed\x59\x0a\x15\x08\x95\xe9\x92\xd2\x2c\x14\x01\xb3\xe9\x3b\x7f\xff\xe6\x6f\x22\x65\xec\x69\xd9\xb8\xda\x24\x2c\x64\x84\x44\x11";
let secret = b"\xa0\x27\x13\x99\xc9\xe3\x2e\xd2\x47\xf6\xd6\x63\x9d\xe6\xec\xcb\x57\x0b\x92\xbb\x17\xfe\xb8\xf1\xc4\x1f\x06\x7c\x55\xfc\xdd\x58";
- let key = Key::import_secret_cv25519(&secret[..], HashAlgorithm::SHA256, SymmetricAlgorithm::AES128, ctime).unwrap();
+ let key: Key = Key4::import_secret_cv25519(&secret[..],
+ HashAlgorithm::SHA256,
+ SymmetricAlgorithm::AES128,
+ ctime).unwrap().into();
match key.mpis {
self::mpis::PublicKey::ECDH{ ref q,.. } => assert_eq!(&q.value[1..], &public[..]),
_ => unreachable!(),
@@ -921,7 +917,8 @@ mod tests {
let d = b"\x14\xC4\x3A\x0C\x3A\x79\xA4\xF7\x63\x0D\x89\x93\x63\x8B\x56\x9C\x29\x2E\xCD\xCF\xBF\xB0\xEC\x66\x52\xC3\x70\x1B\x19\x21\x73\xDE\x8B\xAC\x0E\xF2\xE1\x28\x42\x66\x56\x55\x00\x3B\xFD\x50\xC4\x7C\xBC\x9D\xEB\x7D\xF4\x81\xFC\xC3\xBF\xF7\xFF\xD0\x41\x3E\x50\x3B\x5F\x5D\x5F\x56\x67\x5E\x00\xCE\xA4\x53\xB8\x59\xA0\x40\xC8\x96\x6D\x12\x09\x27\xBE\x1D\xF1\xC2\x68\xFC\xF0\x14\xD6\x52\x77\x07\xC8\x12\x36\x9C\x9A\x5C\xAF\x43\xCC\x95\x20\xBB\x0A\x44\x94\xDD\xB4\x4F\x45\x4E\x3A\x1A\x30\x0D\x66\x40\xAC\x68\xE8\xB0\xFD\xCD\x6C\x6B\x6C\xB5\xF7\xE4\x36\x95\xC2\x96\x98\xFD\xCA\x39\x6C\x1A\x2E\x55\xAD\xB6\xE0\xF8\x2C\xFF\xBC\xD3\x32\x15\x52\x39\xB3\x92\x35\xDB\x8B\x68\xAF\x2D\x4A\x6E\x64\xB8\x28\x63\xC4\x24\x94\x2D\xA9\xDB\x93\x56\xE3\xBC\xD0\xB6\x38\x84\x04\xA4\xC6\x18\x48\xFE\xB2\xF8\xE1\x60\x37\x52\x96\x41\xA5\x79\xF6\x3D\xB7\x2A\x71\x5B\x7A\x75\xBF\x7F\xA2\x5A\xC8\xA1\x38\xF2\x5A\xBD\x14\xFC\xAF\xB4\x54\x83\xA4\xBD\x49\xA2\x8B\x91\xB0\xE0\x4A\x1B\x21\x54\x07\x19\x70\x64\x7C\x3E\x9F\x8D\x8B\xE4\x70\xD1\xE7\xBE\x4E\x5C\xCE\xF1";
let p = b"\xC8\x32\xD1\x17\x41\x4D\x8F\x37\x09\x18\x32\x4C\x4C\xF4\xA2\x15\x27\x43\x3D\xBB\xB5\xF6\x1F\xCF\xD2\xE4\x43\x61\x07\x0E\x9E\x35\x1F\x0A\x5D\xFB\x3A\x45\x74\x61\x73\x73\x7B\x5F\x1F\x87\xFB\x54\x8D\xA8\x85\x3E\xB0\xB7\xC7\xF5\xC9\x13\x99\x8D\x40\xE6\xA6\xD0\x71\x3A\xE3\x2D\x4A\xC3\xA3\xFF\xF7\x72\x82\x14\x52\xA4\xBA\x63\x0E\x17\xCA\xCA\x18\xC4\x3A\x40\x79\xF1\x86\xB3\x10\x4B\x9F\xB2\xAE\x2E\x13\x38\x8D\x2C\xF9\x88\x4C\x25\x53\xEF\xF9\xD1\x8B\x1A\x7C\xE7\xF6\x4B\x73\x51\x31\xFA\x44\x1D\x36\x65\x71\xDA\xFC\x6F";
let q = b"\xCC\x30\xE9\xCC\xCB\x31\x28\xB5\x90\xFF\x06\x62\x42\x5B\x24\x0E\x00\xFE\xE2\x37\xC4\xAC\xBB\x3B\x8F\xF2\x0E\x3F\x78\xCF\x6B\x7C\xE8\x75\x57\x7C\x15\x9D\x1A\x66\xF2\x0A\xE5\xD3\x0B\xE7\x40\xF7\xE7\x00\xB6\x86\xB5\xD9\x20\x67\xE0\x4A\xC0\x90\xA4\x13\x4D\xC9\xB0\x12\xC5\xCD\x4C\xEB\xA1\x91\x2D\x43\x58\x6E\xB6\x75\xA0\x93\xF0\x5B\xC5\x31\xCA\xB7\xC6\x22\x0C\xD3\xEC\x84\xC5\x91\xA1\x5F\x2C\x8E\x07\x5D\xA1\x98\x67\xC5\x7A\x58\x16\x71\x3D\xED\x91\x03\x0D\xD4\x25\x07\x89\x9B\x33\x98\xA3\x70\xD9\xE7\xC8\x17\xA3\xD9";
- let key = Key::import_secret_rsa(&d[..], &p[..], &q[..], ctime).unwrap();
+ let key: Key = Key4::import_secret_rsa(&d[..], &p[..], &q[..], ctime)
+ .unwrap().into();
// PKESK
let c = b"\x8A\x1A\xD4\x82\x91\x6B\xBF\xA1\x65\xD3\x82\x8C\x97\xAB\xD0\x91\xE4\xB4\xC4\x9D\x08\xD8\x8B\xB7\xE6\x13\x3F\x6F\x52\x14\xED\xC4\x77\xB7\x31\x00\xC1\x43\xF9\x62\x53\xBF\x21\x21\x52\x74\x35\xD8\xC7\xA2\x11\x89\xA5\xD5\x21\x98\x6D\x3C\x9F\xF0\xED\xDB\xD7\x0F\xAC\x3C\x15\x25\x34\x52\xC7\x7C\x82\x07\x5A\x99\xC1\xC6\xF6\xF2\x6D\x46\xC8\x56\x59\xE7\xC6\x34\x0C\xCA\x37\x70\xB4\x97\xDA\x18\x14\xC4\x03\x0A\xCB\xE5\x0C\x41\x43\x61\xBA\x32\xB6\x9A\xF3\xDF\x0C\xB0\xCE\xBD\xFE\x72\x6C\xCC\xC1\xE8\xF0\x05\x97\x61\xEA\x30\x10\xB9\x43\xC4\x9A\x41\xED\x72\x27\xA4\xD5\xE7\x08\x41\x6C\x57\x80\xF3\x64\xF0\x45\x70\x27\x36\xBD\x64\x59\x74\xCF\xCD\x39\xE6\xEB\x7C\x62\xC8\x38\x23\xF8\x4C\xB7\x30\x9F\xF1\x40\x4A\xE9\x72\x66\x99\xF7\x2A\x47\x1C\xE7\x12\x20\x58\xBA\x87\x00\xB8\xFC\x54\xBC\xA5\x1D\x7D\x8B\x50\xA4\x4B\xB3\xD7\x44\xC7\x68\x5E\x2D\xBB\xE9\x6E\xC4\xD0\x31\xB0\xD0\xB6\x02\xD1\x74\x6B\xC9\x3D\x19\x32\x3B\xF1\x0E\x74\xF6\x12\x13\xE6\x40\x8F\xA6\x97\xAD\x83\xB0\x84\xD6\xD9\xE5\x25\x8E\x57\x0B\x7A\x7B\xD0\x5C\x29\x96\xED\x29\xED";
@@ -957,7 +954,7 @@ mod tests {
// Ed25519 key
let ctime = at(Timespec::new(1548249630,0));
let q = b"\x57\x15\x45\x1B\x68\xA5\x13\xA2\x20\x0F\x71\x9D\xE3\x05\x3B\xED\xA2\x21\xDE\x61\x5A\xF5\x67\x45\xBB\x97\x99\x43\x53\x59\x7C\x3F";
- let key = Key::import_public_ed25519(q, ctime).unwrap();
+ let key: Key = Key4::import_public_ed25519(q, ctime).unwrap().into();
let mut hashed = SubpacketArea::empty();
let mut unhashed = SubpacketArea::empty();
diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs
index 5eff6652..c1a502b1 100644
--- a/openpgp/src/packet/mod.rs
+++ b/openpgp/src/packet/mod.rs
@@ -30,7 +30,6 @@ pub use self::unknown::Unknown;
pub mod signature;
pub mod one_pass_sig;
pub mod key;
-pub use self::key::Key;
mod userid;
pub use self::userid::UserID;
pub mod user_attribute;
@@ -772,6 +771,85 @@ impl From<SKESK> for Packet {
}
}
+/// Holds a public key, public subkey, private key or private subkey packet.
+///
+/// See [Section 5.5 of RFC 4880] for details.
+///
+/// [Section 5.5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.5
+#[derive(PartialEq, Eq, Hash, Clone, Debug)]
+pub enum Key {
+ /// Key packet version 4.
+ V4(self::key::Key4),
+}
+
+impl fmt::Display for Key {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Key::V4(k) => k.fmt(f),
+ }
+ }
+}
+
+impl Key {
+ /// Gets the version.
+ pub fn version(&self) -> u8 {
+ match self {
+ Key::V4(_) => 4,
+ }
+ }
+
+ /// Compares the public bits of two keys.
+ ///
+ /// This returns Ordering::Equal if the public MPIs, version,
+ /// creation time and algorithm of the two `Key`s match. This
+ /// does not consider the packet's encoding, packet's tag or the
+ /// secret key material.
+ pub fn public_cmp(a: &Self, b: &Self) -> ::std::cmp::Ordering {
+ match (a, b) {
+ (Key::V4(a), Key::V4(b)) => self::key::Key4::public_cmp(a, b),
+ }
+ }
+
+ /// Creates a new key pair from a Key packet with an unencrypted
+ /// secret key.
+ ///
+ /// # Errors
+ ///
+ /// Fails if the secret key is missing, or encrypted.
+ pub fn into_keypair(self) -> Result<::crypto::KeyPair> {
+ match self {
+ Key::V4(p) => p.into_keypair(),
+ }
+ }
+
+ /// Convert the `Key` struct to a `Packet`.
+ pub fn into_packet(self, tag: Tag) -> Result<Packet> {
+ match self {
+ Key::V4(p) => p.into_packet(tag),
+ }
+ }
+}
+
+// Trivial forwarder for singleton enum.
+impl Deref for Key {
+ type Target = self::key::Key4;
+
+ fn deref(&self) -> &Self::Target {
+ match self {
+ Key::V4(ref p) => p,
+ }
+ }
+}
+
+// Trivial forwarder for singleton enum.
+impl DerefMut for Key {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ match self {
+ Key::V4(ref mut p) => p,
+ }
+ }
+}
+
/// Holds an encrypted data packet.
///
/// An encrypted data packet is a container. See [Section 5.13 of RFC
diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs
index 75591ccd..6933b204 100644
--- a/openpgp/src/packet/pkesk.rs
+++ b/openpgp/src/packet/pkesk.rs
@@ -390,6 +390,7 @@ mod tests {
use HashAlgorithm;
use constants::Curve;
use packet::Key;
+ use packet::key::Key4;
use nettle::{curve25519, Yarrow};
use time;
@@ -413,9 +414,9 @@ mod tests {
let private_mpis = mpis::SecretKey::ECDH {
scalar: MPI::new(&sec[..]),
};
- let key = Key::new(time::now().canonicalize(),
- PublicKeyAlgorithm::ECDH, public_mpis, None)
- .unwrap();
+ let key: Key = Key4::new(time::now().canonicalize(),
+ PublicKeyAlgorithm::ECDH, public_mpis, None)
+ .unwrap().into();
let mut rng = Yarrow::default();
let sess_key = SessionKey::new(&mut rng, 32);
let pkesk = PKESK3::for_recipient(SymmetricAlgorithm::AES256, &sess_key,
diff --git a/openpgp/src/packet/prelude.rs b/openpgp/src/packet/prelude.rs
index 54b2bcdd..316be0ef 100644
--- a/openpgp/src/packet/prelude.rs
+++ b/openpgp/src/packet/prelude.rs
@@ -8,6 +8,7 @@ pub use super::{
OnePassSig,
one_pass_sig::OnePassSig3,
Key,
+ key::Key4,
key::SecretKey,
UserID,
UserAttribute,
diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs
index 7e906968..e9a02490 100644
--- a/openpgp/src/packet/signature/mod.rs
+++ b/openpgp/src/packet/signature/mod.rs
@@ -846,6 +846,7 @@ mod test {
use crypto::mpis::MPI;
use TPK;
use parse::Parse;
+ use packet::key::Key4;
#[cfg(feature = "compression-deflate")]
#[test]
@@ -1037,8 +1038,8 @@ mod test {
use constants::Curve;
use packet::key::SecretKey;
- let key = Key::generate_ecc(true, Curve::Ed25519)
- .unwrap();
+ let key: Key = Key4::generate_ecc(true, Curve::Ed25519)
+ .unwrap().into();
let msg = b"Hello, World";
match key.secret() {
@@ -1106,9 +1107,9 @@ mod test {
let private_mpis = mpis::SecretKey::EdDSA {
scalar: MPI::new(&sec[..]),
};
- let key = Key::new(time::now().canonicalize(),
+ let key = Key4::new(time::now().canonicalize(),
PublicKeyAlgorithm::EdDSA, public_mpis, None)
- .unwrap();
+ .unwrap().into();
let msg = b"Hello, World";
let mut hash = HashAlgorithm::SHA256.context().unwrap();
diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs
index 62d9f8b3..6e9b42c4 100644
--- a/openpgp/src/packet/signature/subpacket.rs
+++ b/openpgp/src/packet/signature/subpacket.rs
@@ -2295,7 +2295,8 @@ fn accessors() {
let hash_algo = HashAlgorithm::SHA512;
let hash = hash_algo.context().unwrap();
let mut sig = signature::Builder::new(::constants::SignatureType::Binary);
- let mut key = ::packet::Key::generate_ecc(true, Curve::Ed25519).unwrap();
+ let mut key: ::packet::Key =
+ ::packet::key::Key4::generate_ecc(true, Curve::Ed25519).unwrap().into();
let sec = if let Some(SecretKey::Unencrypted { ref mpis }) = key.secret() {
mpis.clone()
} else {
diff --git a/openpgp/src/parse/key.rs b/openpgp/src/parse/key.rs
index 36c252ba..d2c1e618 100644
--- a/openpgp/src/parse/key.rs
+++ b/openpgp/src/parse/key.rs
@@ -5,7 +5,7 @@ use nettle::hash::insecure_do_not_use::Sha1;
use {
crypto::Hash,
- packet::Key,
+ packet::key::Key4,
KeyID,
Fingerprint,
};
@@ -19,7 +19,7 @@ fn path_to(artifact: &str) -> PathBuf {
.iter().collect()
}
-impl Key {
+impl Key4 {
/// Computes and returns the key's fingerprint as per Section 12.2
/// of RFC 4880.
pub fn fingerprint(&self) -> Fingerprint {
diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs
index c7798308..ff64ac0c 100644
--- a/openpgp/src/parse/parse.rs
+++ b/openpgp/src/parse/parse.rs
@@ -1342,6 +1342,31 @@ impl Key {
/// Parses the body of a public key, public subkey, secret key or
/// secret subkey packet.
fn parse<'a>(mut php: PacketHeaderParser<'a>) -> Result<PacketParser<'a>> {
+ make_php_try!(php);
+ let tag = php.header.ctb.tag;
+ assert!(tag == Tag::PublicKey
+ || tag == Tag::PublicSubkey
+ || tag == Tag::SecretKey
+ || tag == Tag::SecretSubkey);
+ let version = php_try!(php.parse_u8("version"));
+