#crypto #hashing #finite-fields #no-std #ecc

no-std hash2field

实现了类似于https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5中描述的将安全哈希映射到有限域

3个版本 (破坏性更新)

0.4.0 2021年12月20日
0.3.0 2021年12月20日
0.2.0 2021年5月11日

#2525 in 加密学

Apache-2.0

14KB
159

hash2field

这个crate旨在用于无需std的环境。

实现了类似于IETF草案第5节描述的安全哈希映射到有限域。

这个crate旨在由哈希到曲线的实现者调用,无需编写哈希到域的章节,因为这是曲线无关的。

它提供了两个结构体、两个特性和函数hash_to_field

FromRO应该由hash_to_field的调用者实现,并用于将输出摘要转换为域元素。

ExpandMsgExpandMsgXofExpandMsgXmd实现,因此不需要直接实现。

ExpandMsgXmd是实现第5.4.1节的实现,并允许调用者选择固定的输出摘要。

ExpandMsgXof是实现第5.4.2节的实现,并允许调用者选择任何XOF。

hash_to_field使用了在Rust 1.51中实现的const generics。

以下是一个使用它的k256 crate的示例

use hash2field::*;
use digest::generic_array::{GenericArray, typenum::U32};
use k256::FieldElement;
use num_bigint::BigUint;
use num_integer::Integer;
use sha2::Sha256;

const L: usize = 48;
const COUNT: usize = 2;
const OUT: usize = L * COUNT;
const DST: &[u8] = b"QUUX-V01-CS02-with-secp256k1_XMD:SHA-256_SSWU_RO_";

impl FromOkm<L> for FieldElement {
    fn from_okm(data: &[u8; L]) -> Self {
        let p = BigUint::from_bytes_be(&hex::decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F").unwrap());
        let mut x = BigUint::from_bytes_be(&data[..]);
        x = x.mod_floor(&p);
        let mut t = x.to_bytes_be();
        while t.len() < 32 {
            t.insert(0, 0u8);
        }
        let t = GenericArray::<u8, U32>::clone_from_slice(&t);
        FieldElement::from_bytes(&t).unwrap()
    }
}

let output = hash_to_field::<ExpandMsgXmd<Sha256>, FieldElement, L, COUNT, OUT>(b"this is a test", DST);
}

使用ExpandMsgXof非常相似

use hash2field::*;
use digest::generic_array::{GenericArray, typenum::U32};
use k256::FieldElement;
use num_bigint::BigUint;
use num_integer::Integer;
use sha3::Shake256;

const L: usize = 48;
const COUNT: usize = 2;
const OUT: usize = L * COUNT;
const DST: &[u8] = b"QUUX-V01-CS02-with-secp256k1_XOF:SHAKE-256_SSWU_RO_";

impl FromOkm<L> for FieldElement {
    fn from_okm(data: &[u8; L]) -> Self {
        let p = BigUint::from_bytes_be(&hex::decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F").unwrap());
        let mut x = BigUint::from_bytes_be(&data[..]);
        x = x.mod_floor(&p);
        let mut t = x.to_bytes_be();
        while t.len() < 32 {
            t.insert(0, 0u8);
        }
        let t = GenericArray::<u8, U32>::clone_from_slice(&t);
        FieldElement::from_bytes(&t).unwrap()
    }
}

let output = hash_to_field::<ExpandMsgXof<Shake256>, FieldElement, L, COUNT, OUT>(b"this is a test", DST);

依赖关系

~2MB
~42K SLoC