silk.crypto.des_wrap.
Wrap keys with the Triple DES key wrap of RFC 3217 (CMS id-alg-CMS3DESwrap).
When to use#
Use TripleDesKeyWrap where a format or protocol names Triple DES key wrap, such as old CMS
messages or Node's des3-wrap cipher. For new designs, use silk.crypto.aes_wrap.
Details#
The key-encryption key is 24 bytes (K1, K2, K3). TripleDesKeyWrap.wrap appends the first 8
bytes of the SHA-1 of the input as an integrity value, encrypts that with Triple DES in CBC mode
under a caller's 8-byte IV, puts the IV in front, reverses the bytes, and encrypts again in CBC
mode under the fixed IV 4ADDA22C79E82105. The input is a nonzero multiple of 8 bytes, and the
output is 16 bytes longer. As in OpenSSL, any such length is taken, and the key bytes' parity
is not changed. TripleDesKeyWrap.unwrap reverses the steps and checks the integrity value.
Nothing allocates.
Errors#
The functions return a TripleDesKeyWrapError. The checks on lengths come before the first
write. On IntegrityCheckFailed, unwrapping sets the bytes it wrote back to zero.
Gotchas#
The IV must be random for each wrap: RFC 3217 takes it from a random source, and OpenSSL draws
one itself. Take 8 bytes from silk.system.random.
Examples#
Wrap and unwrap a key#
import silk.crypto.des_wrap { TripleDesKeyWrap, TripleDesKeyWrapError }
import silk.core.result { Result }
pub fn main() -> i32 {
let kek: [u8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
let iv: [u8; 8] = [9; 8]
let secret: [u8; 24] = [7; 24]
let mut wrapped: [u8; 40] = [0; 40]
if let Result.Failure { error: _ } = TripleDesKeyWrap.wrap(&kek, &iv, &secret, &mut wrapped) { return 1 }
let mut unwrapped: [u8; 24] = [0; 24]
return match TripleDesKeyWrap.unwrap(&kek, &wrapped, &mut unwrapped) {
Result<usize, TripleDesKeyWrapError>.Success { value } => if value == 24 && unwrapped[0] == 7 { 0 } else { 1 }
Result<usize, TripleDesKeyWrapError>.Failure { error: _ } => 1
}
}Import as TripleDesKeyWrap with import silk.crypto.des_wrap { TripleDesKeyWrap }.
Public declarations: 2.
TripleDesKeyWrapError#
pub enum TripleDesKeyWrapErrorThe reason that a key wrap call was rejected. The checks run in the order of the variants.
InvalidKeyLength#
InvalidKeyLengthThe key-encryption key is not 24 bytes.
InvalidIvLength#
InvalidIvLengthThe IV is not 8 bytes.
InvalidInputLength#
InvalidInputLengthThe input length is not one that the algorithm takes.
OutputTooSmall#
OutputTooSmallThe output is shorter than the bytes the call writes.
IntegrityCheckFailed#
IntegrityCheckFailedThe unwrapped integrity value does not match: the key is wrong or the input was changed.
Implementation Debug for TripleDesKeyWrapError#
impl Debug for TripleDesKeyWrapErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant, such as InvalidKeyLength.
TripleDesKeyWrap#
pub struct TripleDesKeyWrapFunctions that wrap and unwrap keys with Triple DES (RFC 3217).
Details#
The key-encryption key is 24 bytes. Wrapping adds 16 bytes. Nothing allocates.
Implementation TripleDesKeyWrap#
impl TripleDesKeyWrapAssociated function wrapIv#
pub fn wrapIv() -> [u8; 8]Returns the fixed IV of the second encryption, 4ADDA22C79E82105.
Associated function wrap#
pub fn wrap(key: &[u8], iv: &[u8], input: &[u8], output: &mut [u8]) -> Result<usize, TripleDesKeyWrapError>Wraps input (a nonzero multiple of 8 bytes) under key with the random 8-byte iv into the
first input.length + 16 bytes of output, and returns that length.
Errors#
InvalidKeyLengthifkeyis not 24 bytes.InvalidIvLengthifivis not 8 bytes.InvalidInputLengthifinputis empty or not a multiple of 8.OutputTooSmallifoutputis shorter thaninput.length + 16.
Associated function unwrap#
pub fn unwrap(key: &[u8], input: &[u8], output: &mut [u8]) -> Result<usize, TripleDesKeyWrapError>Unwraps input (a multiple of 8 bytes, at least 24) under key, checks its integrity value,
writes the key to the first input.length - 16 bytes of output, and returns that length.
Errors#
InvalidKeyLengthifkeyis not 24 bytes.InvalidInputLengthifinputis shorter than 24 bytes or not a multiple of 8.OutputTooSmallifoutputis shorter thaninput.length - 16.IntegrityCheckFailedif the integrity value does not match. The written bytes are zero.
Category: Cryptography.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.