Offentliggjort kilde
Download kilde ZIP
CH-J Tools
Gennemse mapper og filer til en specifik applikationsudgivelse.
CH-J / Server Manager
1704 filer
0.1.2-beta
Tilføjet: · Bygget:
1
//! The signature formats are protocol data, not alternate crypto primitives.2
use super::wire::*;3
use crate::core::error::CoreResult;4
use pgp::types::KeyDetails;6
#[derive(Clone)]7
pub struct Signature {8
pub version: u8,9
pub typ: u8,10
pub algorithm: u8,11
pub hash_algorithm: u8,12
pub created: u32,13
pub hashed: Vec<u8>,14
pub digest_prefix: [u8; 2],15
pub value: Vec<u8>,16
pub head: Vec<u8>,17
}18
pub fn subpacket(typ: u8, data: &[u8]) -> CoreResult<Vec<u8>> {19
let mut v = Vec::new();20
write_len(&mut v, data.len() + 1)?;21
v.push(typ);22
v.extend(data);23
Ok(v)24
}25
pub fn subpackets(data: &[u8]) -> CoreResult<Vec<(u8, &[u8])>> {26
let mut r = Reader::new(data);27
let mut out = Vec::new();28
while !r.rest().is_empty() {29
if out.len() >= 128 {30
return Err(invalid());31
}32
let n = packet_len(&mut r)?;33
let typ = r.u8()?;34
if n == 0 {35
return Err(invalid());36
}37
out.push((typ, r.take(n - 1)?));38
}39
Ok(out)40
}41
impl Signature {42
pub fn parse(bytes: &[u8]) -> CoreResult<Self> {43
let mut r = Reader::new(bytes);44
let version = r.u8()?;45
let (typ, algorithm, hash_algorithm, created, hashed, _unhashed, head) = if version <= 3 {46
if ![2, 3].contains(&version) || r.u8()? != 5 {47
return Err(invalid());48
}49
let typ = r.u8()?;50
let created = r.u32()?;51
r.take(8)?;52
let alg = r.u8()?;53
let hash = r.u8()?;54
(55
typ,56
alg,57
hash,58
created,59
Vec::new(),60
Vec::new(),61
bytes[2..7].to_vec(),62
)63
} else if version == 5 {64
let typ = r.u8()?;65
let alg = r.u8()?;66
let hash = r.u8()?;67
let n = r.u16()? as usize;68
let hashed = r.take(n)?.to_vec();69
let head = bytes[..r.pos].to_vec();70
let n = r.u16()? as usize;71
let unhashed = r.take(n)?.to_vec();72
let packets = subpackets(&hashed)?;73
let created = packets74
.iter()75
.rev()76
.find_map(|(t, b)| {77
(*t & 127 == 2 && b.len() == 4)78
.then(|| u32::from_be_bytes((*b).try_into().unwrap_or([0; 4])))79
})80
.ok_or_else(invalid)?;81
subpackets(&unhashed)?;82
(typ, alg, hash, created, hashed, unhashed, head)83
} else {84
return Err(invalid());85
};86
if ![1, 3, 17, 19, 22].contains(&algorithm)87
|| (version == 588
&& ![8, 9, 10, 11].contains(&hash_algorithm)89
&& !(algorithm == 17 && hash_algorithm == 2))90
{91
return Err(invalid());92
}93
let digest_prefix = r.take(2)?.try_into().map_err(|_| invalid())?;94
let value = r.rest().to_vec();95
if value.is_empty() {96
return Err(invalid());97
}98
Ok(Self {99
version,100
typ,101
algorithm,102
hash_algorithm,103
created,104
hashed,105
digest_prefix,106
value,107
head,108
})109
}110
pub fn digest(&self, data: &[u8]) -> CoreResult<Vec<u8>> {111
if self.version <= 3 {112
return hash(self.hash_algorithm, &[data, &self.head]);113
}114
let mut trailer = vec![5, 255];115
trailer.extend((self.head.len() as u64).to_be_bytes());116
if [0, 1].contains(&self.typ) {117
hash(self.hash_algorithm, &[data, &self.head, &[0; 6], &trailer])118
} else {119
hash(self.hash_algorithm, &[data, &self.head, &trailer])120
}121
}122
pub fn verify(&self, params: &Parameters, data: &[u8]) -> CoreResult<()> {123
// Unknown critical subpackets must never grant capabilities or authorize signing.124
if subpackets(&self.hashed)?.iter().any(|(t, _)| {125
t & 128 != 0 && ![2, 3, 9, 11, 16, 21, 22, 25, 27, 29, 30, 32, 33].contains(&(t & 127))126
}) {127
return Err(invalid());128
}129
for (typ, bytes) in subpackets(&self.hashed)? {130
let valid = match typ & 127 {131
2 | 3 | 9 => bytes.len() == 4,132
16 => bytes.len() == 8,133
25 => bytes.len() == 1,134
27 => !bytes.is_empty(),135
33 => bytes.len() == 33 && bytes[0] == 5,136
32 => !bytes.is_empty(),137
_ => true,138
};139
if !valid {140
return Err(invalid());141
}142
}143
let digest = self.digest(data)?;144
if digest[..2] != self.digest_prefix {145
return Err(invalid());146
}147
params.verify(self.hash_algorithm, &digest, self.algorithm, &self.value)148
}149
pub fn field(&self, typ: u8) -> Option<&[u8]> {150
subpackets(&self.hashed)151
.ok()?152
.into_iter()153
.rev()154
.find_map(|(t, b)| (t & 127 == typ).then_some(b))155
}156
pub fn duration(&self, typ: u8) -> Option<u32> {157
self.field(typ)158
.filter(|b| b.len() == 4)159
.map(|b| u32::from_be_bytes(b.try_into().unwrap_or([0; 4])))160
}161
pub fn current(&self, now: u32) -> bool {162
self.created <= now.saturating_add(300)163
&& self164
.duration(3)165
.is_none_or(|duration| duration == 0 || self.created.saturating_add(duration) > now)166
}167
}168
pub fn create(169
version: u8,170
typ: u8,171
algorithm: u8,172
created: u32,173
key_id: &[u8],174
hashed: Vec<u8>,175
unhashed: Vec<u8>,176
data: &[u8],177
params: &Parameters,178
) -> CoreResult<Packet> {179
let hash_algorithm = if version <= 3 {180
1181
} else if algorithm == 17 {182
crate::core::openpgp_algorithms::signing_hash(params.public.public_params()).into()183
} else if algorithm == 22 {184
10185
} else {186
8187
};188
let mut body = vec![version];189
if version <= 3 {190
if key_id.len() != 8 {191
return Err(invalid());192
}193
body.push(5);194
body.push(typ);195
body.extend(created.to_be_bytes());196
body.extend(key_id);197
body.extend([algorithm, hash_algorithm]);198
} else {199
if version != 5 || hashed.len() > u16::MAX as usize || unhashed.len() > u16::MAX as usize {200
return Err(invalid());201
}202
body.extend([typ, algorithm, hash_algorithm]);203
body.extend((hashed.len() as u16).to_be_bytes());204
body.extend(&hashed);205
body.extend((unhashed.len() as u16).to_be_bytes());206
body.extend(&unhashed);207
}208
// Parse the framing first so generation and verification share the exact spec trailer.209
let mut framing = body.clone();210
framing.extend([0, 0, 0]);211
let signature = Signature::parse(&framing)?;212
let digest = signature.digest(data)?;213
body.extend(&digest[..2]);214
body.extend(params.sign(hash_algorithm, &digest)?);215
let packet = Packet::new(2, body);216
Signature::parse(&packet.body)?.verify(params, data)?;217
Ok(packet)218
}SHA-256
2598e9b9899a7634df092ab555d31e12c4ecd7117d4405fe01d77454374917fdCH-J Proprietary Software License 1.14 · Kilden leveres under CH-J Proprietary Software License 1.14. Dens tilgængelighed ændrer ikke licensbetingelserne eller giver yderligere rettigheder.
Arkiv SHA-256
ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f