Fuente publicada
Descargar fuente ZIP
CH-J Tools
Busque directorios y archivos para obtener una versión de aplicación específica.
CH-J / Server Manager
1704 archivos
0.1.2-beta
Añadido: · Construido:
1
//! LibrePGP draft-koch-librepgp-06, not RFC 9580 V6 with a changed version.2
use super::{3
certificate::{binding_data, certificate_data, Certificate},4
key::{self, Key},5
protect,6
signature::{self, subpacket},7
wire::*,8
};9
use crate::core::error::CoreResult;10
use pgp::types::Timestamp;11
use serde_json::{json, Value};13
pub fn expiry(created: u32, payload: &Value) -> CoreResult<Option<Vec<u8>>> {14
let Some(v) = payload15
.get("expiresAt")16
.filter(|v| !v.is_null() && **v != 0)17
else {18
return Ok(None);19
};20
let at = v.as_u64().ok_or_else(invalid)?;21
if at <= Timestamp::now().as_secs() as u64 {22
return Err(invalid());23
}24
let duration = u32::try_from(at.checked_sub(created as u64).ok_or_else(invalid)?)25
.map_err(|_| invalid())?;26
Ok(Some(subpacket(9, &duration.to_be_bytes())?))27
}28
pub fn hashed(key: &Key, created: u32) -> CoreResult<Vec<u8>> {29
let mut bytes = subpacket(2, &created.to_be_bytes())?;30
let mut issuer = vec![5];31
issuer.extend(key.fingerprint()?);32
bytes.extend(subpacket(33, &issuer)?);33
Ok(bytes)34
}35
pub fn signature(36
key: &Key,37
params: &Parameters,38
typ: u8,39
hashed: Vec<u8>,40
data: &[u8],41
) -> CoreResult<Packet> {42
signature::create(43
5,44
typ,45
key.algorithm,46
Timestamp::now().as_secs(),47
&key.key_id()?,48
hashed,49
subpacket(16, &key.key_id()?)?,50
data,51
params,52
)53
}54
pub fn capabilities(algorithm: &str, caps: &str, primary: bool) -> CoreResult<u8> {55
crate::core::openpgp_algorithms::validate(5, algorithm, caps)?;56
let allowed = match algorithm {57
"rsa3072" | "rsa4096" => {58
if primary {59
"CSAE"60
} else {61
"SAE"62
}63
}64
"ed25519" => {65
if primary {66
"CSA"67
} else {68
"SA"69
}70
}71
"curve25519" if !primary => "E",72
id if crate::core::openpgp_algorithms::is_dsa(id) => {73
if primary {74
"CS"75
} else {76
"S"77
}78
}79
_ => return Err(invalid()),80
};81
if caps.is_empty()82
|| caps.chars().any(|c| !allowed.contains(c))83
|| (primary && !caps.contains('C'))84
{85
return Err(invalid());86
}87
Ok((if caps.contains('C') { 1 } else { 0 })88
| (if caps.contains('S') { 2 } else { 0 })89
| (if caps.contains('A') { 32 } else { 0 })90
| (if caps.contains('E') { 12 } else { 0 }))91
}92
pub fn subkey(93
primary: &Key,94
params: &Parameters,95
spec: &Value,96
password: &str,97
progress: &dyn Fn(&str) -> CoreResult<()>,98
) -> CoreResult<Vec<Packet>> {99
let role = spec["role"].as_str().unwrap_or("sign");100
if !["sign", "encrypt", "authenticate"].contains(&role) {101
return Err(invalid());102
}103
let caps = spec["capabilities"].as_str().unwrap_or(match role {104
"sign" => "S",105
"authenticate" => "A",106
_ => "E",107
});108
let algorithm = spec["algorithm"].as_str().unwrap_or(if role == "encrypt" {109
"curve25519"110
} else {111
"ed25519"112
});113
let bits = capabilities(algorithm, caps, false)?;114
let now = Timestamp::now().as_secs();115
let expiration = expiry(now, spec)?;116
progress("subkey")?;117
let generated = key::generate(5, now, 0, algorithm)?;118
let key = &generated.key;119
let data = binding_data(primary, key)?;120
let mut hash = hashed(primary, now)?;121
hash.extend(subpacket(27, &[bits])?);122
if let Some(exp) = expiration {123
hash.extend(exp)124
}125
if bits & 2 != 0 {126
let back = signature(key, &generated.parameters, 0x19, hashed(key, now)?, &data)?;127
hash.extend(subpacket(32, &back.body)?);128
}129
let binding = signature(primary, params, 0x18, hash, &data)?;130
progress("protect")?;131
let protected = protect::seal(key, &generated.plain, password, 7)?;132
Ok(vec![protected, binding])133
}134
pub fn build(135
payload: &Value,136
uid: &str,137
progress: &dyn Fn(&str) -> CoreResult<()>,138
) -> CoreResult<(Certificate, String)> {139
let now = Timestamp::now().as_secs();140
let password = payload["passphrase"].as_str().unwrap_or("");141
let algorithm = payload["algorithm"].as_str().unwrap_or("ed25519");142
let caps = payload["primaryCapabilities"].as_str().unwrap_or("CS");143
let bits = capabilities(algorithm, caps, true)?;144
let expiration = expiry(now, payload)?;145
let specs = payload["subkeys"]146
.as_array()147
.cloned()148
.unwrap_or_else(|| vec![json!({"role":"encrypt","algorithm":"curve25519"})]);149
if specs.len() > 8 {150
return Err(invalid());151
}152
for spec in &specs {153
let role=spec["role"].as_str().unwrap_or("sign");154
if !["sign","encrypt","authenticate"].contains(&role){return Err(invalid())}155
let caps=spec["capabilities"].as_str().unwrap_or(match role{"encrypt"=>"E","authenticate"=>"A",_=>"S"});156
let algorithm=spec["algorithm"].as_str().unwrap_or(if role=="encrypt"{"curve25519"}else{"ed25519"});157
capabilities(algorithm,caps,false)?;expiry(now,spec)?;158
}159
progress("primary")?;160
let generated = key::generate(5, now, 0, algorithm)?;161
let key = &generated.key;162
let mut hash = hashed(key, now)?;163
hash.extend(subpacket(27, &[bits])?);164
hash.extend(subpacket(25, &[1])?);165
hash.extend(subpacket(11, &[9, 8, 7])?);166
hash.extend(subpacket(21, &[10, 9, 8])?);167
hash.extend(subpacket(22, &[2, 1, 0])?);168
if let Some(exp) = expiration {169
hash.extend(exp)170
}171
let self_sig = signature(172
key,173
&generated.parameters,174
0x13,175
hash,176
&certificate_data(key, uid.as_bytes())?,177
)?;178
let mut packets = vec![179
Packet::new(6, key.public.clone()),180
Packet::new(13, uid.as_bytes().to_vec()),181
self_sig,182
];183
for spec in &specs {184
packets.extend(subkey(185
key,186
&generated.parameters,187
spec,188
password,189
progress,190
)?);191
}192
progress("revocation")?;193
let revocation = signature(194
key,195
&generated.parameters,196
0x20,197
hashed(key, now)?,198
&key.prefix()?,199
)?;200
progress("protect")?;201
packets[0] = protect::seal(key, &generated.plain, password, 5)?;202
progress("verify")?;203
let cert = Certificate::parse(&encode(&packets, 5)?)?;204
if cert.metadata()?["usable"] != true {205
return Err(invalid());206
}207
let mut revoked = cert.public_packets()?;208
revoked.insert(1, revocation);209
Ok((cert, armor("PUBLIC KEY BLOCK", &encode(&revoked, 5)?)))210
}SHA-256
880ff87468ed7ac3850db685fd49dbe87d1812550e9ceb51ed059649b304d932CH-J Proprietary Software License 1.14 · La fuente se proporciona en el CH-J Proprietary Software License 1.14. Su disponibilidad no cambia los términos de la licencia ni otorga derechos adicionales.
Archivo SHA-256
ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f