Közzétett forrás
Letöltés forrás ZIP
CH-J Tools
Könyvtárak és fájlok böngészése egy adott alkalmazás kiadásához.
CH-J / Server Manager
1704 fájlok
0.1.2-beta
Hozzáadva: · Beépített:
1
//! Historical IDEA/CFB and LibrePGP V5 secret-packet framing. V6 is untouched.2
use super::{key::Key, wire::*};3
use crate::core::error::CoreResult;4
use bytes::BytesMut;5
use pgp::{6
crypto::{aead::AeadAlgorithm, hash::HashAlgorithm, sym::SymmetricKeyAlgorithm as Cipher},7
ser::Serialize,8
types::StringToKey,9
};10
use rand::RngCore;11
use subtle::ConstantTimeEq;12
use zeroize::{Zeroize, Zeroizing};13
struct WipeBuffer(BytesMut);14
impl Drop for WipeBuffer {15
fn drop(&mut self) {16
self.0.as_mut().zeroize();17
}18
}19
fn cipher(id: u8) -> CoreResult<Cipher> {20
if ![1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13].contains(&id) {21
return Err(invalid());22
}23
Ok(Cipher::from(id))24
}25
fn s2k(reader: &mut Reader) -> CoreResult<StringToKey> {26
let id = *reader.rest().first().ok_or_else(invalid)?;27
let len = match id {28
0 => 2,29
1 => 10,30
3 => 11,31
_ => return Err(invalid()),32
};33
let bytes = reader.take(len)?;34
if ![1, 2, 3, 8, 9, 10, 11].contains(&bytes[1]) {35
return Err(invalid());36
}37
crypto(StringToKey::try_from_reader(std::io::Cursor::new(bytes)))38
}39
fn legacy_cfb(40
data: &[u8],41
key: &[u8],42
iv: &[u8],43
algorithm: Cipher,44
encrypt: bool,45
) -> CoreResult<Zeroizing<Vec<u8>>> {46
let mut r = Reader::new(data);47
let mut out = Zeroizing::new(Vec::with_capacity(data.len()));48
let mut feedback = Zeroizing::new(iv.to_vec());49
for _ in 0..4 {50
let bits = r.u16()?;51
let source = r.take((bits as usize).div_ceil(8))?;52
let mut value = Zeroizing::new(source.to_vec());53
if encrypt {54
crypto(algorithm.encrypt_with_iv_regular(key, &feedback, &mut value))?;55
} else {56
crypto(algorithm.decrypt_with_iv_regular(key, &feedback, &mut value))?;57
}58
// Resynchronization aligns each MPI, retaining the last block of ciphertext.59
let ciphertext = if encrypt { value.as_slice() } else { source };60
let mut next = Zeroizing::new(feedback.to_vec());61
next.extend(ciphertext);62
let n = next.len();63
feedback.copy_from_slice(&next[n - iv.len()..]);64
out.extend(bits.to_be_bytes());65
out.extend(value.as_slice());66
}67
r.done()?;68
Ok(out)69
}70
pub fn seal(key: &Key, plain: &[u8], password: &str, secret_tag: u8) -> CoreResult<Packet> {71
let mut body = Zeroizing::new(key.public.clone());72
if password.is_empty() {73
body.push(0);74
if key.version == 5 {75
body.push(0);76
body.extend((plain.len() as u32).to_be_bytes());77
}78
body.extend(plain);79
body.extend(checksum(plain));80
} else if key.version <= 3 {81
let algorithm = Cipher::IDEA;82
let derived = StringToKey::Simple {83
hash_alg: HashAlgorithm::Md5,84
}85
.derive_key(password.as_bytes(), 16)86
.map_err(|_| invalid())?;87
let mut iv = [0u8; 8];88
rand::thread_rng().fill_bytes(&mut iv);89
body.push(1);90
body.extend(iv);91
body.extend(legacy_cfb(plain, derived.as_ref(), &iv, algorithm, true)?.as_slice());92
body.extend(checksum(plain));93
} else {94
let algorithm = Cipher::AES256;95
let mut salt = [0u8; 8];96
rand::thread_rng().fill_bytes(&mut salt);97
let s2k = StringToKey::IteratedAndSalted {98
hash_alg: HashAlgorithm::Sha256,99
salt,100
count: 224,101
};102
// V5 usage 254 is the interoperable LibrePGP secret format. AES-256 CFB103
// protects the parameter bytes and their SHA-1 integrity checksum; S2K uses SHA-256.104
let derived = crypto(s2k.derive_key(password.as_bytes(), 32))?;105
let mut iv = [0u8; 16];106
rand::thread_rng().fill_bytes(&mut iv);107
let mut encrypted = Zeroizing::new(Vec::with_capacity(plain.len() + 20));108
encrypted.extend(plain);109
encrypted.extend(hash(2, &[plain])?);110
crypto(algorithm.encrypt_with_iv_regular(derived.as_ref(), &iv, &mut encrypted))?;111
let mut parameters = vec![9];112
parameters.extend(crypto(s2k.to_bytes())?);113
parameters.extend(iv);114
body.extend([254, parameters.len() as u8]);115
body.extend(parameters);116
body.extend((encrypted.len() as u32).to_be_bytes());117
body.extend(encrypted.as_slice());118
}119
Ok(Packet {120
tag: secret_tag,121
body,122
})123
}124
pub fn open(key: &Key, password: &str) -> CoreResult<Zeroizing<Vec<u8>>> {125
let bytes = key.secret.as_ref().ok_or_else(invalid)?;126
let mut r = Reader::new(bytes);127
let usage = r.u8()?;128
if key.version <= 3 {129
if usage == 0 {130
if r.rest().len() < 2 {131
return Err(invalid());132
}133
let n = r.rest().len() - 2;134
let plain = r.take(n)?;135
let expected = r.take(2)?;136
if !bool::from(checksum(plain).ct_eq(expected)) {137
return Err(invalid());138
}139
return Ok(Zeroizing::new(plain.to_vec()));140
}141
let algorithm = cipher(usage)?;142
let iv = r.take(algorithm.block_size())?;143
if r.rest().len() < 2 {144
return Err(invalid());145
}146
let n = r.rest().len() - 2;147
let encrypted = r.take(n)?;148
let expected = r.take(2)?;149
let derived = crypto(150
StringToKey::Simple {151
hash_alg: HashAlgorithm::Md5,152
}153
.derive_key(password.as_bytes(), algorithm.key_size()),154
)?;155
let plain = legacy_cfb(encrypted, derived.as_ref(), iv, algorithm, false)?;156
if !bool::from(checksum(&plain).ct_eq(expected)) {157
return Err(invalid());158
}159
return Ok(plain);160
}161
let count = r.u8()? as usize;162
let mut params = Reader::new(r.take(count)?);163
if usage == 0 {164
params.done()?;165
let n = r.u32()? as usize;166
let plain = r.take(n)?;167
let expected = r.take(2)?;168
r.done()?;169
if !bool::from(checksum(plain).ct_eq(expected)) {170
return Err(invalid());171
}172
return Ok(Zeroizing::new(plain.to_vec()));173
}174
if ![253, 254].contains(&usage) {175
return Err(invalid());176
}177
let algorithm = cipher(params.u8()?)?;178
if ![Cipher::AES128, Cipher::AES192, Cipher::AES256].contains(&algorithm) {179
return Err(invalid());180
}181
if usage == 253 && params.u8()? != 2 {182
return Err(invalid());183
}184
let derivation = s2k(&mut params)?;185
let iv = params.take(algorithm.block_size())?;186
params.done()?;187
let n = r.u32()? as usize;188
let encrypted = r.take(n)?;189
r.done()?;190
let derived = crypto(derivation.derive_key(password.as_bytes(), algorithm.key_size()))?;191
if usage == 253 {192
if encrypted.len() < 16 || iv.len() != 16 || iv[15] != 0 {193
return Err(invalid());194
}195
let mut associated = vec![0xc0 | key.tag, algorithm.into(), 2];196
associated.extend(&key.public);197
let mut buffer = WipeBuffer(BytesMut::with_capacity(encrypted.len()));198
buffer.0.extend_from_slice(encrypted);199
crypto(AeadAlgorithm::Ocb.decrypt_in_place(200
&algorithm,201
derived.as_ref(),202
&iv[..15],203
&associated,204
&mut buffer.0,205
))?;206
return Ok(Zeroizing::new(buffer.0.to_vec()));207
}208
let mut plain = Zeroizing::new(encrypted.to_vec());209
crypto(algorithm.decrypt_with_iv_regular(derived.as_ref(), iv, &mut plain))?;210
if plain.len() < 20 {211
return Err(invalid());212
}213
let n = plain.len() - 20;214
let digest = hash(2, &[&plain[..n]])?;215
if !bool::from(digest.ct_eq(&plain[n..])) {216
return Err(invalid());217
}218
plain.truncate(n);219
Ok(plain)220
}SHA-256
874c27ba2b17c8b68308114a2ef62d9b5876b48a0e5a1933a587a5a87a4c1333CH-J Proprietary Software License 1.14 · A forrás a CH-J Proprietary Software License 1.14 alatt található. Rendelkezése nem változtatja meg a licenc feltételeit, és nem ad további jogokat.
Archive SHA-256
ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f