use chrono::{DateTime, Utc};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CipherSuite {
Rsa2k,
Rsa4k,
#[default]
Cv25519,
Cv25519Modern,
NistP256,
NistP384,
NistP521,
}
impl std::str::FromStr for CipherSuite {
type Err = String;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"rsa2k" | "rsa2048" => Ok(CipherSuite::Rsa2k),
"rsa4k" | "rsa4096" => Ok(CipherSuite::Rsa4k),
"cv25519" | "curve25519" | "ed25519" | "ed25519legacy" => Ok(CipherSuite::Cv25519),
"cv25519modern" | "curve25519modern" | "x25519" => Ok(CipherSuite::Cv25519Modern),
"nistp256" | "p256" | "secp256r1" => Ok(CipherSuite::NistP256),
"nistp384" | "p384" | "secp384r1" => Ok(CipherSuite::NistP384),
"nistp521" | "p521" | "secp521r1" => Ok(CipherSuite::NistP521),
_ => Err(format!("unknown cipher suite: {}", s)),
}
}
}
impl CipherSuite {
pub fn name(&self) -> &'static str {
match self {
CipherSuite::Rsa2k => "RSA 2048",
CipherSuite::Rsa4k => "RSA 4096",
CipherSuite::Cv25519 => "Curve25519 (Legacy)",
CipherSuite::Cv25519Modern => "Curve25519 (Modern)",
CipherSuite::NistP256 => "NIST P-256",
CipherSuite::NistP384 => "NIST P-384",
CipherSuite::NistP521 => "NIST P-521",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SubkeyFlags {
pub encryption: bool,
pub signing: bool,
pub authentication: bool,
}
impl SubkeyFlags {
pub fn all() -> Self {
Self {
encryption: true,
signing: true,
authentication: true,
}
}
pub fn encryption_only() -> Self {
Self {
encryption: true,
signing: false,
authentication: false,
}
}
pub fn signing_only() -> Self {
Self {
encryption: false,
signing: true,
authentication: false,
}
}
pub fn from_bitmask(mask: u8) -> Self {
Self {
encryption: (mask & 1) != 0,
signing: (mask & 2) != 0,
authentication: (mask & 4) != 0,
}
}
pub fn to_bitmask(&self) -> u8 {
let mut mask = 0u8;
if self.encryption {
mask |= 1;
}
if self.signing {
mask |= 2;
}
if self.authentication {
mask |= 4;
}
mask
}
}
impl Default for SubkeyFlags {
fn default() -> Self {
Self::all()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyType {
Encryption,
Signing,
Authentication,
Certification,
Unknown,
}
impl std::fmt::Display for KeyType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
KeyType::Encryption => write!(f, "encryption"),
KeyType::Signing => write!(f, "signing"),
KeyType::Authentication => write!(f, "authentication"),
KeyType::Certification => write!(f, "certification"),
KeyType::Unknown => write!(f, "unknown"),
}
}
}
#[derive(Debug, Clone)]
pub struct SubkeyInfo {
pub key_id: String,
pub fingerprint: String,
pub creation_time: DateTime<Utc>,
pub expiration_time: Option<DateTime<Utc>>,
pub key_type: KeyType,
pub is_revoked: bool,
pub algorithm: String,
pub bit_length: usize,
}
#[derive(Debug, Clone)]
pub struct CertificateInfo {
pub user_ids: Vec<UserIDInfo>,
pub fingerprint: String,
pub key_id: String,
pub is_secret: bool,
pub creation_time: DateTime<Utc>,
pub expiration_time: Option<DateTime<Utc>>,
pub can_primary_sign: bool,
pub subkeys: Vec<SubkeyInfo>,
}
#[derive(Debug, Clone)]
pub struct KeyCipherDetails {
pub fingerprint: String,
pub algorithm: String,
pub bit_length: usize,
}
#[derive(Debug)]
pub struct GeneratedKey {
pub public_key: String,
pub secret_key: Vec<u8>,
pub fingerprint: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum CertificationType {
Generic = 0,
Persona = 1,
Casual = 2,
Positive = 3,
}
impl CertificationType {
pub fn to_signature_type(self) -> u8 {
match self {
CertificationType::Generic => 0x10,
CertificationType::Persona => 0x11,
CertificationType::Casual => 0x12,
CertificationType::Positive => 0x13,
}
}
}
#[derive(Debug, Clone)]
pub struct RsaPublicKey {
pub n: String,
pub e: String,
}
#[derive(Debug, Clone)]
pub enum SigningPublicKey {
Rsa(RsaPublicKey),
Ed25519 {
public: String,
},
Ecdsa {
curve: String,
point: String,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct UIDCertification {
pub certification_type: String,
pub creation_time: Option<DateTime<Utc>>,
pub issuers: Vec<(String, String)>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UserIDInfo {
pub value: String,
pub revoked: bool,
pub certifications: Vec<UIDCertification>,
}
#[derive(Debug, Clone)]
pub struct AvailableSubkey {
pub fingerprint: String,
pub key_id: String,
pub creation_time: DateTime<Utc>,
pub expiration_time: Option<DateTime<Utc>>,
pub key_type: KeyType,
pub algorithm: String,
pub bit_length: usize,
}
impl CipherSuite {
pub fn primary_key_type(&self) -> pgp::composed::KeyType {
match self {
CipherSuite::Rsa2k => pgp::composed::KeyType::Rsa(2048),
CipherSuite::Rsa4k => pgp::composed::KeyType::Rsa(4096),
CipherSuite::Cv25519 => pgp::composed::KeyType::Ed25519Legacy,
CipherSuite::Cv25519Modern => pgp::composed::KeyType::Ed25519,
CipherSuite::NistP256 => {
pgp::composed::KeyType::ECDSA(pgp::crypto::ecc_curve::ECCCurve::P256)
}
CipherSuite::NistP384 => {
pgp::composed::KeyType::ECDSA(pgp::crypto::ecc_curve::ECCCurve::P384)
}
CipherSuite::NistP521 => {
pgp::composed::KeyType::ECDSA(pgp::crypto::ecc_curve::ECCCurve::P521)
}
}
}
pub fn encryption_key_type(&self) -> pgp::composed::KeyType {
match self {
CipherSuite::Rsa2k => pgp::composed::KeyType::Rsa(2048),
CipherSuite::Rsa4k => pgp::composed::KeyType::Rsa(4096),
CipherSuite::Cv25519 => {
pgp::composed::KeyType::ECDH(pgp::crypto::ecc_curve::ECCCurve::Curve25519)
}
CipherSuite::Cv25519Modern => pgp::composed::KeyType::X25519,
CipherSuite::NistP256 => {
pgp::composed::KeyType::ECDH(pgp::crypto::ecc_curve::ECCCurve::P256)
}
CipherSuite::NistP384 => {
pgp::composed::KeyType::ECDH(pgp::crypto::ecc_curve::ECCCurve::P384)
}
CipherSuite::NistP521 => {
pgp::composed::KeyType::ECDH(pgp::crypto::ecc_curve::ECCCurve::P521)
}
}
}
}