use std::io::Cursor;
use pgp::composed::{SignedSecretKey, SignedPublicKey, Deserializable};
use pgp::ser::Serialize;
use pgp::types::KeyDetails;
use crate::error::{Error, Result};
pub(crate) fn parse_secret_key(data: &[u8]) -> Result<SignedSecretKey> {
let cursor = Cursor::new(data);
match SignedSecretKey::from_armor_single(cursor) {
Ok((key, _headers)) => Ok(key),
Err(_) => {
let cursor = Cursor::new(data);
SignedSecretKey::from_bytes(cursor)
.map_err(|e| Error::Parse(e.to_string()))
}
}
}
pub(crate) fn parse_public_key(data: &[u8]) -> Result<SignedPublicKey> {
let cursor = Cursor::new(data);
if let Ok((key, _headers)) = SignedPublicKey::from_armor_single(cursor) {
return Ok(key);
}
let cursor = Cursor::new(data);
if let Ok(key) = SignedPublicKey::from_bytes(cursor) {
return Ok(key);
}
if let Ok(secret_key) = parse_secret_key(data) {
return Ok(secret_key.to_public_key());
}
Err(Error::Parse("no matching packet found".to_string()))
}
pub(crate) fn parse_cert(data: &[u8]) -> Result<(SignedPublicKey, bool)> {
if let Ok(secret_key) = parse_secret_key(data) {
let public_key = secret_key.to_public_key();
return Ok((public_key, true));
}
let public_key = parse_public_key(data)?;
Ok((public_key, false))
}
pub(crate) fn secret_key_to_bytes(key: &SignedSecretKey) -> Result<Vec<u8>> {
key.to_bytes()
.map_err(|e| Error::Crypto(e.to_string()))
}
pub(crate) fn public_key_to_armored(key: &SignedPublicKey) -> Result<String> {
key.to_armored_string(None.into())
.map_err(|e| Error::Crypto(e.to_string()))
}
pub(crate) fn fingerprint_to_hex(key: &impl KeyDetails) -> String {
hex::encode_upper(key.fingerprint().as_bytes())
}
pub(crate) fn keyid_to_hex(key: &impl KeyDetails) -> String {
hex::encode_upper(key.legacy_key_id().as_ref())
}
pub(crate) fn system_time_to_datetime(st: std::time::SystemTime) -> chrono::DateTime<chrono::Utc> {
chrono::DateTime::from(st)
}
pub(crate) fn get_algorithm_name(key: &impl KeyDetails) -> String {
use pgp::crypto::public_key::PublicKeyAlgorithm;
match key.algorithm() {
PublicKeyAlgorithm::RSA => "RSA".to_string(),
PublicKeyAlgorithm::RSAEncrypt => "RSA".to_string(),
PublicKeyAlgorithm::RSASign => "RSA".to_string(),
PublicKeyAlgorithm::EdDSALegacy | PublicKeyAlgorithm::Ed25519 => "EdDSA".to_string(),
PublicKeyAlgorithm::ECDH => "ECDH".to_string(),
PublicKeyAlgorithm::ECDSA => "ECDSA".to_string(),
PublicKeyAlgorithm::X25519 => "X25519".to_string(),
PublicKeyAlgorithm::X448 => "X448".to_string(),
PublicKeyAlgorithm::Ed448 => "Ed448".to_string(),
PublicKeyAlgorithm::DSA => "DSA".to_string(),
PublicKeyAlgorithm::Elgamal => "Elgamal".to_string(),
algo => format!("{:?}", algo),
}
}
pub(crate) fn get_key_bit_size(key: &impl KeyDetails) -> usize {
use pgp::crypto::public_key::PublicKeyAlgorithm;
match key.algorithm() {
PublicKeyAlgorithm::RSA | PublicKeyAlgorithm::RSAEncrypt | PublicKeyAlgorithm::RSASign => {
2048
}
PublicKeyAlgorithm::EdDSALegacy | PublicKeyAlgorithm::Ed25519 => 256,
PublicKeyAlgorithm::X25519 => 256,
PublicKeyAlgorithm::X448 => 448,
PublicKeyAlgorithm::Ed448 => 448,
PublicKeyAlgorithm::ECDH => {
256
}
PublicKeyAlgorithm::ECDSA => 256,
PublicKeyAlgorithm::DSA => 2048,
PublicKeyAlgorithm::Elgamal => 2048,
_ => 0,
}
}