4 个版本
使用旧的 Rust 2015
0.0.5 | 2014年12月17日 |
---|---|
0.0.4 | 2014年12月14日 |
0.0.3 | 2014年12月12日 |
0.0.1 | 2014年12月11日 |
#1638 in 加密学
42KB
928 行
椭圆曲线密码学
一个纯Rust®的椭圆曲线算术和加密库。
通过在您的 Cargo.toml
中添加以下内容进行安装
[dependencies.ecc]
version = "*"
必须呼吁我的代码很糟糕并警告您自行承担风险的段落:我已经尝试防止任何计时或无效曲线攻击,但这是我第一次用Rust编写的代码,而且我也可能是唯一阅读过这段代码的人。有一些测试说代码是正确的,也有一些基准测试说它不会非常慢,但我不知道我是否相信它们。这些都是正在进行中的工作。
待办事项
- ElGamal加密
- ECDSA / ElGamal签名
基础知识
目前仅实现了Diffie-Hellman密钥交换的高级操作
extern crate ecc;
use ecc::fields::{P256, R256}; // NIST's fields for P-256
use ecc::curves::C256; // NIST's curve P-256
use ecc::crypto::DiffieHellman;
fn main() {
type Curve = C192<P192, R192>;
type Point = AffinePoint<Curve, P192, R192>;
let (X, x): (Point, _) = DiffieHellman::key_gen();
let out = X.serialize();
// out: Vec<uint> -> Send to the other person.
// x: BigUint -> Kept secret.
// X -----> Other person
// Y: Vec<uint> <-----
let c: Curve = C192;
let in = c.unserialize(Y);
let s: Option<Point> = DiffieHellman::shared(&x, &in);
// Will return None if trickery occured.
// Will return the shared secret Some(...), which should be serialized and
// put through a KDF or something and then used in a cipher/MAC.
}
域
总共有六个域被实现:P192
、P256
和 P521
是对应NIST曲线的基础域。R192
、R256
和 R521
,然而,是作用于它们对应曲线基础点的域。
创建一个域很容易,但作用不大
let f: P192 = P192;
创建一个域元素更有趣
extern crate num;
use num::bigint::ToBigUint;
use ecc::fields::{FieldElem, P192};
...
let x: FieldElem<P192> = FieldElem { limbs: 3i.to_biguint().unwrap() }
// Or any other BigUint in the `limbs` field.
域运算可以应用于域元素,使用正常的单目/双目运算符(取反、加、减、乘、除)。调用 x.invert()
将返回 x
的逆,调用 x.pow(exp)
,其中 exp
是一个 BigUint
,将 x
提到 exp
的幂。
域元素不支持顺序,但可以使用 ==
运算符进行相等性测试。
域元素可以通过调用 x.serialize()
序列化为字节向量,或者通过调用 field.unserialize(...)
反序列化。
默认情况下,指数和相等性测试都是常数时间的。
曲线
目前仅实现了三个NIST曲线:C192
、C256
和 C521
。
创建一个曲线类似于创建一个域
let c: C192<P192, R192> = C192;
调用 c.G()
将返回曲线的基点在仿射坐标中的表示。调用 .to_jacobian()
将其转换为雅可比坐标,或者通过调用 .to_affine()
在雅可比点上将其转换回仿射坐标。
支持在相同坐标系上的点的取反、加法和减法操作。点也可以被 BigUint
乘以。要检查一个点是否有效,请调用 A.is_valid()
。要检查一个点是否为零(无穷远点),请调用 A.is_zero()
。
可以通过调用 A.serialize()
将点序列化为字节数组,或者通过调用 curve.unserialize(...)
进行反序列化。
默认情况下,点乘法和等式测试是常数时间的。
extern crate num;
use std::num::FromStrRadix;
use fields::{P192, R192};
use curves::{Curve, C192};
fn main() {
let curve C192<P192, R192> = C192;
let a: BigUint = FromStrRadix::from_str_radix("7e48c5ab7f43e4d9c17bd9712627dcc76d4df2099af7c8e5", 16).unwrap();
let G = curve.G().to_jacobian();
let A = a * G;
}
依赖关系
~465KB