silk.crypto.aes_wrap.

Wrap keys with the AES key wrap algorithms of RFC 3394 and RFC 5649 (NIST SP 800-38F KW, KWP).

When to use#

Use AesKeyWrap to encrypt one key under another where a format names AES key wrap, such as CMS, JOSE A128KW, or Node's id-aes128-wrap and id-aes128-wrap-pad.

Details#

The key-encryption key is 16, 24, or 32 bytes. AesKeyWrap.wrap takes a multiple of 8 bytes, at least 16, and adds 8 bytes. AesKeyWrap.wrapPadded takes any nonzero length, pads it to a multiple of 8, and adds 8 bytes. Unwrapping checks the integrity value, so a wrong key or a changed input fails. The IV is 8 bytes for KW and 4 bytes for KWP; AesKeyWrap.defaultIv and AesKeyWrap.defaultPaddedIv return the RFC values. Nothing allocates.

Errors#

The functions return an AesKeyWrapError. The checks on lengths come before the first write. Unwrapping works in the output buffer, and on IntegrityCheckFailed it sets the bytes it used back to zero.

Examples#

Wrap and unwrap a key#

silk
import silk.crypto.aes_wrap { AesKeyWrap, AesKeyWrapError }
import silk.core.result { Result }

pub fn main() -> i32 {
  let kek: [u8; 16] = [1; 16]
  let secret: [u8; 16] = [2; 16]
  let iv = AesKeyWrap.defaultIv()
  let mut wrapped: [u8; 24] = [0; 24]
  if let Result.Failure { error: _ } = AesKeyWrap.wrap(&kek, &iv, &secret, &mut wrapped) { return 1 }
  let mut unwrapped: [u8; 16] = [0; 16]
  return match AesKeyWrap.unwrap(&kek, &iv, &wrapped, &mut unwrapped) {
    Result<usize, AesKeyWrapError>.Success { value } => if value == 16 && unwrapped[0] == 2 { 0 } else { 1 }
    Result<usize, AesKeyWrapError>.Failure { error: _ } => 1
  }
}

Import as AesKeyWrap with import silk.crypto.aes_wrap { AesKeyWrap }.

Public declarations: 2.

AesKeyWrapError#

silk
pub enum AesKeyWrapError

The reason that a key wrap call was rejected. The checks run in the order of the variants.

InvalidKeyLength#

silk
InvalidKeyLength

The key-encryption key is not 16, 24, or 32 bytes.

InvalidIvLength#

silk
InvalidIvLength

The IV is not 8 bytes (KW) or 4 bytes (KWP).

InvalidInputLength#

silk
InvalidInputLength

The input length is not one that the algorithm takes.

OutputTooSmall#

silk
OutputTooSmall

The output is shorter than the bytes the call writes.

IntegrityCheckFailed#

silk
IntegrityCheckFailed

The unwrapped integrity value does not match: the key is wrong or the input was changed.

Implementation Debug for AesKeyWrapError#

silk
impl Debug for AesKeyWrapError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant, such as InvalidKeyLength.

AesKeyWrap#

silk
pub struct AesKeyWrap

Functions that wrap and unwrap keys with AES (RFC 3394 KW and RFC 5649 KWP).

Details#

The key-encryption key is 16, 24, or 32 bytes. Wrapping adds 8 bytes. Nothing allocates.

Implementation AesKeyWrap#

silk
impl AesKeyWrap

Associated function defaultIv#

silk
pub fn defaultIv() -> [u8; 8]

Returns the default KW IV of RFC 3394, A6A6A6A6A6A6A6A6.

Associated function defaultPaddedIv#

silk
pub fn defaultPaddedIv() -> [u8; 4]

Returns the default KWP IV of RFC 5649, A65959A6.

Associated function wrap#

silk
pub fn wrap(key: &[u8], iv: &[u8], input: &[u8], output: &mut [u8]) -> Result<usize, AesKeyWrapError>

Wraps input (a multiple of 8 bytes, at least 16) under key with the 8-byte iv into the first input.length + 8 bytes of output, and returns that length.

Errors#

  • InvalidKeyLength if key is not 16, 24, or 32 bytes.

  • InvalidIvLength if iv is not 8 bytes.

  • InvalidInputLength if input is shorter than 16 bytes or not a multiple of 8.

  • OutputTooSmall if output is shorter than input.length + 8.

Associated function unwrap#

silk
pub fn unwrap(key: &[u8], iv: &[u8], input: &[u8], output: &mut [u8]) -> Result<usize, AesKeyWrapError>

Unwraps input (a multiple of 8 bytes, at least 24) under key, checks it against the 8-byte iv, writes the key to the first input.length - 8 bytes of output, and returns that length.

Errors#

  • InvalidKeyLength if key is not 16, 24, or 32 bytes.

  • InvalidIvLength if iv is not 8 bytes.

  • InvalidInputLength if input is shorter than 24 bytes or not a multiple of 8.

  • OutputTooSmall if output is shorter than input.length - 8.

  • IntegrityCheckFailed if the integrity value is not iv. The written bytes are zero.

Associated function wrapPadded#

silk
pub fn wrapPadded(key: &[u8], iv: &[u8], input: &[u8], output: &mut [u8]) -> Result<usize, AesKeyWrapError>

Pads input (1 byte or more) to a multiple of 8, wraps it under key with the 4-byte iv into output, and returns the wrapped length, which is the padded length plus 8.

Errors#

  • InvalidKeyLength if key is not 16, 24, or 32 bytes.

  • InvalidIvLength if iv is not 4 bytes.

  • InvalidInputLength if input is empty or longer than 2^32 - 1 bytes.

  • OutputTooSmall if output is shorter than the wrapped length.

Associated function unwrapPadded#

silk
pub fn unwrapPadded(key: &[u8], iv: &[u8], input: &[u8], output: &mut [u8]) -> Result<usize, AesKeyWrapError>

Unwraps input (a multiple of 8 bytes, at least 16) under key, checks the 4-byte iv, the length, and the padding, writes the key to output, and returns its length.

Errors#

  • InvalidKeyLength if key is not 16, 24, or 32 bytes.

  • InvalidIvLength if iv is not 4 bytes.

  • InvalidInputLength if input is shorter than 16 bytes or not a multiple of 8.

  • OutputTooSmall if output is shorter than input.length - 8, the padded length.

  • IntegrityCheckFailed if the IV, length, or padding is wrong. The bytes it used 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.

View the source of this page