#aead #encryption #zero-allocation #data #aes #mode #payload

no-std aes-ccm

一个纯Rust,#![no_std],零分配AES-CCM实现,从TinyCrypt移植而来,使用RustCrypto的AES

7个版本 (4个重大更新)

0.5.0 2020年6月13日
0.4.1 2020年3月17日
0.4.0 2019年12月1日
0.3.0 2019年9月9日
0.1.0 2019年8月19日

2613密码学

Download history 45/week @ 2024-03-13 37/week @ 2024-03-20 38/week @ 2024-03-27 48/week @ 2024-04-03 104/week @ 2024-04-10 79/week @ 2024-04-17 41/week @ 2024-04-24 27/week @ 2024-05-01 59/week @ 2024-05-08 120/week @ 2024-05-15 34/week @ 2024-05-22 41/week @ 2024-05-29 26/week @ 2024-06-05 30/week @ 2024-06-12 95/week @ 2024-06-19 44/week @ 2024-06-26

每月下载量 202

MIT/Apache

47KB
789

aes-ccm

Latest version Documentation License

一个纯Rust,#![no_std],零分配AES-CCM实现,从TinyCrypt移植而来,使用RustCrypto的AES(支持可选的硬件实现)。

它实现了aead::AeadInPlace特质,因此可以与其他实现无缝配合使用。

概述

CCM("带有CBC-MAC的计数器")模式是NIST批准的操作模式,定义在SP 800-38C中。

此实现接受

  1. 非空有效载荷和关联数据(它加密和验证有效载荷,并验证关联数据)。
  2. 非空有效载荷和空关联数据(它加密和验证有效载荷)。
  3. 非空关联数据和空有效载荷(它退化到关联数据的验证模式)。

实现接受0到2^16字节之间的任何长度的有效载荷和0到(2^16 - 2^8)字节之间的任何长度的关联数据。

用法

use aes_ccm::{
    aead::{consts::U8, Aead, NewAead, Payload},
    Aes128Ccm,
};

let key = [
    0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
    0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
];

// `U8` represents the tag size as a `typenum` unsigned (8-bytes here)
let ccm = Aes128Ccm::<U8>::new(&key.into());

let nonce = [
    0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, 0xA1, 0xA2, 0xA3,
    0xA4, 0xA5,
];
let msg = [
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
    0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
    0x1E,
];
let associated_data = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];

let ciphertext = ccm
    .encrypt(
        &nonce.into(),
        Payload {
            aad: &associated_data,
            msg: &msg,
        },
    )
    .unwrap();

let plaintext = ccm
    .decrypt(
        &nonce.into(),
        Payload {
            aad: &associated_data,
            msg: &ciphertext,
        },
    )
    .unwrap();

assert_eq!(&msg[..], plaintext.as_slice());

原地使用(消除alloc要求)

此crate有一个可选的alloc功能,可以在例如没有堆的微控制器环境中禁用。

方法 AeadInPlace::encrypt_in_placeAeadInPlace::decrypt_in_place 可以接受实现了 aead::Buffer 特性的任何类型,该特性包含用于加密的明文或用于解密的密文。

注意,如果您启用此crate的 heapless 功能,您将获得 aead::Buffer 的实现,适用于 heapless::Vec(由 aead crate作为 aead::heapless::Vec 重导出),然后可以将它作为 buffer 参数传递给就地加密和解密方法

use aes_ccm::{
    aead::{
        consts::{U128, U8},
        heapless::Vec,
        AeadInPlace, NewAead,
    },
    Aes128Ccm,
};

let key = [
    0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
    0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
];

// `U8` represents the tag size as a `typenum` unsigned (8-bytes here)
let ccm = Aes128Ccm::<U8>::new(&key.into());

let nonce = [
    0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, 0xA1, 0xA2, 0xA3,
    0xA4, 0xA5,
];
let associated_data = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
let plaintext = [
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
    0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
    0x1E,
];

let mut buffer: Vec<u8, U128> = Vec::new();
buffer.extend_from_slice(&plaintext).unwrap();

// Encrypt `buffer` in-place, replacing the plaintext contents with
// ciphertext
ccm.encrypt_in_place(&nonce.into(), &associated_data, &mut buffer)
    .unwrap();
// `buffer` now contains the message ciphertext
assert_ne!(&buffer, &plaintext);

// Decrypt `buffer` in-place, replacing its ciphertext contents with the
// original plaintext
ccm.decrypt_in_place(&nonce.into(), &associated_data, &mut buffer)
    .unwrap();
assert_eq!(&buffer, &plaintext);

安全性

我不是密码学家,这个文档没有经过任何审核。然而,它是TinyCrypt的谨慎移植,所以如果它是可靠的,那么这个也应该是。

MAC长度参数是一个重要参数,用于估计对碰撞攻击(旨在找到产生相同认证标签的不同消息)的安全性。实现接受任何介于4和16之间的偶数,如SP 800-38C中建议的那样。

RFC 3610,它还指定了CCM,提出了一些相关的安全建议,例如

  • 建议大多数应用程序使用大于8的MAC长度。
  • 使用相同的nonce对使用相同密钥加密的两个不同消息会破坏CCM模式的安全性。

许可证

根据您的选择,许可如下

这是TinyCrypt的CCM模式的移植,其许可证文件在LICENSE-3RD-PARTY中。

贡献

除非您明确表示,否则您有意提交的任何贡献,根据Apache-2.0许可证定义,将按上述方式双许可,不附加任何额外条款或条件。

依赖关系

约600KB
约14K SLoC