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 加密学

MIT 许可证

42KB
928

椭圆曲线密码学

一个纯Rust®的椭圆曲线算术和加密库。

通过在您的 Cargo.toml 中添加以下内容进行安装

[dependencies.ecc]
version = "*"

必须呼吁我的代码很糟糕并警告您自行承担风险的段落:我已经尝试防止任何计时或无效曲线攻击,但这是我第一次用Rust编写的代码,而且我也可能是唯一阅读过这段代码的人。有一些测试说代码是正确的,也有一些基准测试说它不会非常慢,但我不知道我是否相信它们。这些都是正在进行中的工作。

待办事项

  1. ElGamal加密
  2. 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.
}

总共有六个域被实现:P192P256P521 是对应NIST曲线的基础域。R192R256R521,然而,是作用于它们对应曲线基础点的域。

创建一个域很容易,但作用不大

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曲线:C192C256C521

创建一个曲线类似于创建一个域

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