ascon: 2018 edition upgrade, lints, docs (#34)

- Bumps the crate's edition to 2018, which is MSRV-compatible
- Adds a more expansive set of lints
- Adds the `missing_docs` lint, and adds docs where missing
This commit is contained in:
Tony Arcieri 2023-02-11 11:54:59 -07:00 committed by GitHub
parent 5831f8bd51
commit 2e113f5f96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 109 additions and 52 deletions

2
Cargo.lock generated
View File

@ -4,7 +4,7 @@ version = 3
[[package]]
name = "ascon"
version = "0.1.4"
version = "0.2.0-pre"
dependencies = [
"byteorder",
]

View File

@ -1,10 +1,18 @@
[package]
name = "ascon"
version = "0.1.4"
authors = ["quininer kel <quininer@live.com>"]
description = "A implementation of ASCON authenticated encryption."
repository = "https://github.com/quininer/ascon"
version = "0.2.0-pre"
description = """
Pure Rust implementation of Ascon, a family of authenticated encryption and
hashing algorithms designed to be lightweight and easy to implement
"""
authors = ["quininer kel <quininer@live.com>", "RustCrypto Developers"]
license = "Apache-2.0 OR MIT"
documentation = "https://docs.rs/ascon"
repository = "https://github.com/RustCrypto/sponges/tree/master/ascon"
keywords = ["crypto", "sponge"]
categories = ["cryptography", "no-std"]
readme = "README.md"
edition = "2018"
[dependencies]
byteorder = { version = "1.0", default-features = false }

View File

@ -64,6 +64,7 @@ dual licensed as above, without any additional terms or conditions.
[//]: # (links)
[RustCrypto]: https://github.com/rustcrypto
[Ascon]: https://ascon.iaik.tugraz.at/
[New standard for lightweight cryptography]: https://www.nist.gov/news-events/news/2023/02/nist-selects-lightweight-cryptography-algorithms-protect-small-devices
[NIST Lightweight Cryptography]: https://csrc.nist.gov/projects/lightweight-cryptography/finalists
[CAESAR competition]: https://competitions.cr.yp.to/caesar-submissions.html

View File

@ -1,9 +1,42 @@
extern crate byteorder;
//! Pure Rust implementation of [Ascon], a family of authenticated encryption and
//! hashing algorithms designed to be lightweight and easy to implement.
//!
//! ## About
//!
//! Ascon is a family of lightweight algorithms built on a core permutation
//! algorithm. These algorithms include:
//!
//! - Authenticated Encryption with Associated Data (AEAD)
//! - Hash functions (HASH) and extendible-output functions (XOF)
//! - Pseudo-random functions (PRF) and message authentication codes (MAC)
//!
//! Ascon has been selected as [new standard for lightweight cryptography] in the
//! [NIST Lightweight Cryptography] competition, and has also been selected as the
//! primary choice for lightweight authenticated encryption in the final
//! portfolio of the [CAESAR competition].
//!
//! [Ascon]: https://ascon.iaik.tugraz.at/
//! [New standard for lightweight cryptography]: https://www.nist.gov/news-events/news/2023/02/nist-selects-lightweight-cryptography-algorithms-protect-small-devices
//! [NIST Lightweight Cryptography]: https://csrc.nist.gov/projects/lightweight-cryptography/finalists
//! [CAESAR competition]: https://competitions.cr.yp.to/caesar-submissions.html
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
)]
#![warn(
clippy::mod_module_files,
clippy::unwrap_used,
missing_docs,
rust_2018_idioms,
unused_lifetimes,
unused_qualifications
)]
mod ops;
mod util;
use ops::{finalization, initialization, permutation, process_aad};
use crate::ops::{finalization, initialization, permutation, process_aad};
const KEY_LEN: usize = 16;
const S_SIZE: usize = 320 / 8;
@ -11,12 +44,17 @@ const RATE: usize = 128 / 8;
const A: usize = 12;
const B: usize = 8;
/// Decryption errors.
#[derive(Debug)]
pub enum DecryptFail {
/// Invalid tag length.
TagLengthError,
/// Authentication failure (invalid tag).
AuthenticationFail,
}
/// AEAD encryption.
pub fn aead_encrypt(key: &[u8], iv: &[u8], message: &[u8], aad: &[u8]) -> (Vec<u8>, [u8; KEY_LEN]) {
let s = aad.len() / RATE + 1;
let t = message.len() / RATE + 1;
@ -69,6 +107,7 @@ pub fn aead_encrypt(key: &[u8], iv: &[u8], message: &[u8], aad: &[u8]) -> (Vec<u
(output, tag)
}
/// AEAD decryption.
pub fn aead_decrypt(
key: &[u8],
iv: &[u8],
@ -127,36 +166,42 @@ pub fn aead_decrypt(
}
}
#[test]
fn ascon_test() {
let key = [0; 16];
let iv = [0; 16];
let aad = [0; 16];
let message = [0; 64];
#[cfg(test)]
mod tests {
use super::{aead_decrypt, aead_encrypt};
use crate::util;
let (ciphertext, tag) = aead_encrypt(&key, &iv, &message, &aad);
let plaintext = aead_decrypt(&key, &iv, &ciphertext, &aad, &tag).unwrap();
assert_eq!(plaintext, &message[..]);
assert!(util::eq(&message, &plaintext));
}
#[test]
fn ascon_tv_test() {
let key = [0; 16];
let iv = [0; 16];
let aad = b"ASCON";
let message = b"ascon";
let (ciphertext, tag) = aead_encrypt(&key, &iv, message, aad);
assert_eq!(ciphertext, [0x4c, 0x8c, 0x42, 0x89, 0x49]);
assert_eq!(
tag,
[
0x65, 0xfd, 0x17, 0xb6, 0xd3, 0x0c, 0xd8, 0x76, 0xa0, 0x5a, 0x8e, 0xfc, 0xec, 0xad,
0x99, 0x3a
]
);
let plaintext = aead_decrypt(&key, &iv, &ciphertext, aad, &tag).unwrap();
assert_eq!(plaintext, message);
#[test]
fn ascon_test() {
let key = [0; 16];
let iv = [0; 16];
let aad = [0; 16];
let message = [0; 64];
let (ciphertext, tag) = aead_encrypt(&key, &iv, &message, &aad);
let plaintext = aead_decrypt(&key, &iv, &ciphertext, &aad, &tag).unwrap();
assert_eq!(plaintext, &message[..]);
assert!(util::eq(&message, &plaintext));
}
#[test]
fn ascon_tv_test() {
let key = [0; 16];
let iv = [0; 16];
let aad = b"ASCON";
let message = b"ascon";
let (ciphertext, tag) = aead_encrypt(&key, &iv, message, aad);
assert_eq!(ciphertext, [0x4c, 0x8c, 0x42, 0x89, 0x49]);
assert_eq!(
tag,
[
0x65, 0xfd, 0x17, 0xb6, 0xd3, 0x0c, 0xd8, 0x76, 0xa0, 0x5a, 0x8e, 0xfc, 0xec, 0xad,
0x99, 0x3a
]
);
let plaintext = aead_decrypt(&key, &iv, &ciphertext, aad, &tag).unwrap();
assert_eq!(plaintext, message);
}
}

View File

@ -1,4 +1,7 @@
use util::{u64_to_u8, u8_to_u64};
use crate::{
util::{u64_to_u8, u8_to_u64},
A, B, KEY_LEN, RATE, S_SIZE,
};
pub fn permutation(s: &mut [u8], start: usize, rounds: usize) {
let mut x = [0; 5];
@ -47,17 +50,17 @@ pub fn permutation(s: &mut [u8], start: usize, rounds: usize) {
}
pub fn initialization(s: &mut [u8], key: &[u8], nonce: &[u8]) {
s[0] = ::KEY_LEN as u8 * 8;
s[1] = ::RATE as u8 * 8;
s[2] = ::A as u8;
s[3] = ::B as u8;
s[0] = KEY_LEN as u8 * 8;
s[1] = RATE as u8 * 8;
s[2] = A as u8;
s[3] = B as u8;
let mut pos = ::S_SIZE - 2 * ::KEY_LEN;
let mut pos = S_SIZE - 2 * KEY_LEN;
s[pos..pos + key.len()].copy_from_slice(key);
pos += ::KEY_LEN;
pos += KEY_LEN;
s[pos..pos + nonce.len()].copy_from_slice(nonce);
permutation(s, 12 - ::A, ::A);
permutation(s, 12 - A, A);
for (i, &b) in key.iter().enumerate() {
s[pos + i] ^= b;
@ -66,19 +69,19 @@ pub fn initialization(s: &mut [u8], key: &[u8], nonce: &[u8]) {
pub fn finalization(s: &mut [u8], key: &[u8]) {
for (i, &b) in key.iter().enumerate() {
s[::RATE + i] ^= b;
s[RATE + i] ^= b;
}
permutation(s, 12 - ::A, ::A);
permutation(s, 12 - A, A);
for (i, &b) in key.iter().enumerate() {
s[::S_SIZE - ::KEY_LEN + i] ^= b;
s[S_SIZE - KEY_LEN + i] ^= b;
}
}
pub fn process_aad(ss: &mut [u8], aa: &[u8], s: usize) {
for i in 0..s {
for j in 0..::RATE {
ss[j] ^= aa[i * ::RATE + j];
for j in 0..RATE {
ss[j] ^= aa[i * RATE + j];
}
permutation(ss, 12 - ::B, ::B);
permutation(ss, 12 - B, B);
}
}