ENHANCED: Faster Rust-based crypto_curve_scalar_mult/4 using OpenSSL.
This commit is contained in:
@@ -41,3 +41,4 @@ ring = "0.16.13"
|
|||||||
ripemd160 = "0.8.0"
|
ripemd160 = "0.8.0"
|
||||||
sha3 = "0.8.2"
|
sha3 = "0.8.2"
|
||||||
blake2 = "0.8.1"
|
blake2 = "0.8.1"
|
||||||
|
openssl = { version = "0.10.29", features = ["vendored"] }
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ pub enum SystemClauseType {
|
|||||||
CryptoPasswordHash,
|
CryptoPasswordHash,
|
||||||
CryptoDataEncrypt,
|
CryptoDataEncrypt,
|
||||||
CryptoDataDecrypt,
|
CryptoDataDecrypt,
|
||||||
|
CryptoCurveScalarMult,
|
||||||
Ed25519Sign,
|
Ed25519Sign,
|
||||||
Ed25519Verify,
|
Ed25519Verify,
|
||||||
Ed25519NewKeyPair,
|
Ed25519NewKeyPair,
|
||||||
@@ -488,6 +489,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::CryptoPasswordHash => clause_name!("$crypto_password_hash"),
|
&SystemClauseType::CryptoPasswordHash => clause_name!("$crypto_password_hash"),
|
||||||
&SystemClauseType::CryptoDataEncrypt => clause_name!("$crypto_data_encrypt"),
|
&SystemClauseType::CryptoDataEncrypt => clause_name!("$crypto_data_encrypt"),
|
||||||
&SystemClauseType::CryptoDataDecrypt => clause_name!("$crypto_data_decrypt"),
|
&SystemClauseType::CryptoDataDecrypt => clause_name!("$crypto_data_decrypt"),
|
||||||
|
&SystemClauseType::CryptoCurveScalarMult => clause_name!("$crypto_curve_scalar_mult"),
|
||||||
&SystemClauseType::Ed25519Sign => clause_name!("$ed25519_sign"),
|
&SystemClauseType::Ed25519Sign => clause_name!("$ed25519_sign"),
|
||||||
&SystemClauseType::Ed25519Verify => clause_name!("$ed25519_verify"),
|
&SystemClauseType::Ed25519Verify => clause_name!("$ed25519_verify"),
|
||||||
&SystemClauseType::Ed25519NewKeyPair => clause_name!("$ed25519_new_keypair"),
|
&SystemClauseType::Ed25519NewKeyPair => clause_name!("$ed25519_new_keypair"),
|
||||||
@@ -663,6 +665,7 @@ impl SystemClauseType {
|
|||||||
("$crypto_password_hash", 4) => Some(SystemClauseType::CryptoPasswordHash),
|
("$crypto_password_hash", 4) => Some(SystemClauseType::CryptoPasswordHash),
|
||||||
("$crypto_data_encrypt", 5) => Some(SystemClauseType::CryptoDataEncrypt),
|
("$crypto_data_encrypt", 5) => Some(SystemClauseType::CryptoDataEncrypt),
|
||||||
("$crypto_data_decrypt", 5) => Some(SystemClauseType::CryptoDataDecrypt),
|
("$crypto_data_decrypt", 5) => Some(SystemClauseType::CryptoDataDecrypt),
|
||||||
|
("$crypto_curve_scalar_mult", 5) => Some(SystemClauseType::CryptoCurveScalarMult),
|
||||||
("$ed25519_sign", 3) => Some(SystemClauseType::Ed25519Sign),
|
("$ed25519_sign", 3) => Some(SystemClauseType::Ed25519Sign),
|
||||||
("$ed25519_verify", 3) => Some(SystemClauseType::Ed25519Verify),
|
("$ed25519_verify", 3) => Some(SystemClauseType::Ed25519Verify),
|
||||||
("$ed25519_new_keypair", 1) => Some(SystemClauseType::Ed25519NewKeyPair),
|
("$ed25519_new_keypair", 1) => Some(SystemClauseType::Ed25519NewKeyPair),
|
||||||
|
|||||||
@@ -683,45 +683,6 @@ ed25519_verify(Key0, Data0, Signature0, Options) :-
|
|||||||
hex_bytes(Signature0, Signature),
|
hex_bytes(Signature0, Signature),
|
||||||
'$ed25519_verify'(Key, Data, Signature).
|
'$ed25519_verify'(Key, Data, Signature).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
Modular multiplicative inverse.
|
|
||||||
|
|
||||||
Compute Y = X^(-1) mod p, using the extended Euclidean algorithm.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
multiplicative_inverse_modulo_p(X, P, Y) :-
|
|
||||||
eea(X, P, _, _, Y),
|
|
||||||
R #= X*Y mod P,
|
|
||||||
zcompare(C, 1, R),
|
|
||||||
must_be_one(C, X, P, Y).
|
|
||||||
|
|
||||||
must_be_one(=, _, _, _).
|
|
||||||
must_be_one(>, X, P, Y) :- throw(multiplicative_inverse_modulo_p(X,P,Y)).
|
|
||||||
must_be_one(<, X, P, Y) :- throw(multiplicative_inverse_modulo_p(X,P,Y)).
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
Extended Euclidean algorithm.
|
|
||||||
|
|
||||||
Computes the GCD and the Bézout coefficients S and T.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
eea(I, J, G, S, T) :-
|
|
||||||
State0 = state(1,0,0,1),
|
|
||||||
eea_loop(I, J, State0, G, S, T).
|
|
||||||
|
|
||||||
eea_loop(I, J, State0, G, S, T) :-
|
|
||||||
zcompare(C, 0, J),
|
|
||||||
eea_(C, I, J, State0, G, S, T).
|
|
||||||
|
|
||||||
eea_(=, I, _, state(_,_,U,V), I, U, V).
|
|
||||||
eea_(<, I0, J0, state(S0,T0,U0,V0), I, U, V) :-
|
|
||||||
Q #= I0 // J0,
|
|
||||||
R #= I0 mod J0,
|
|
||||||
S1 #= U0 - (Q*S0),
|
|
||||||
T1 #= V0 - (Q*T0),
|
|
||||||
eea_loop(J0, R, state(S1,T1,S0,T0), I, U, V).
|
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Operations on Elliptic Curves
|
Operations on Elliptic Curves
|
||||||
=============================
|
=============================
|
||||||
@@ -742,90 +703,37 @@ eea_(<, I0, J0, state(S0,T0,U0,V0), I, U, V) :-
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
An elliptic curve over a prime field F_p is represented as:
|
An elliptic curve over a prime field F_p is represented as:
|
||||||
|
|
||||||
curve(P,A,B,point(X,Y),Order,Cofactor).
|
curve(Name,P,A,B,point(X,Y),Order,FieldLength,Cofactor).
|
||||||
|
|
||||||
First, we define suitable accessors.
|
First, we define suitable accessors.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
curve_p(curve(P,_,_,_,_,_), P).
|
curve_name(curve(Name,_,_,_,_,_,_,_), Name).
|
||||||
curve_a(curve(_,A,_,_,_,_), A).
|
curve_p(curve(_,P,_,_,_,_,_,_), P).
|
||||||
curve_b(curve(_,_,B,_,_,_), B).
|
curve_a(curve(_,_,A,_,_,_,_,_), A).
|
||||||
|
curve_b(curve(_,_,_,B,_,_,_,_), B).
|
||||||
|
curve_field_length(curve(_,_,_,_,_,_,FieldLength,_), FieldLength).
|
||||||
|
|
||||||
crypto_curve_order(curve(_,_,_,_,Order,_), Order).
|
crypto_curve_generator(curve(_,_,_,_,G,_,_,_), G).
|
||||||
crypto_curve_generator(curve(_,_,_,G,_,_), G).
|
crypto_curve_order(curve(_,_,_,_,_,Order,_,_), Order).
|
||||||
|
|
||||||
|
crypto_curve_scalar_mult(Curve, Scalar, point(X,Y), point(RX, RY)) :-
|
||||||
|
must_be_on_curve(Curve, point(X,Y)),
|
||||||
|
curve_name(Curve, Name),
|
||||||
|
curve_field_length(Curve, L0),
|
||||||
|
L #= 2*L0, % for hex encoding
|
||||||
|
phrase(format_("04~|~`0t~16r~*+~`0t~16r~*+", [X,L,Y,L]), Hex),
|
||||||
|
hex_bytes(Hex, Bytes),
|
||||||
|
'$crypto_curve_scalar_mult'(Name, Scalar, Bytes, SX, SY),
|
||||||
|
number_chars(RX, SX),
|
||||||
|
number_chars(RY, SY).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Scalar point multiplication.
|
?- crypto_name_curve(secp256k1, Curve),
|
||||||
|
crypto_curve_generator(Curve, G),
|
||||||
R = k*Q.
|
crypto_curve_scalar_mult(Curve, 2, G, R).
|
||||||
|
|
||||||
The Montgomery ladder method is used to mitigate side-channel
|
|
||||||
attacks such as timing attacks, since the number of multiplications
|
|
||||||
and additions is independent of the private key K. This method does
|
|
||||||
not even reveal the key's Hamming weight (number of 1s).
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
crypto_curve_scalar_mult(Curve, K, Q, R) :-
|
|
||||||
msb(K, Upper),
|
|
||||||
scalar_multiplication(Curve, K, Upper, ml(null,Q)-R),
|
|
||||||
must_be_on_curve(Curve, R).
|
|
||||||
|
|
||||||
scalar_multiplication(Curve, K, I, R0-R) :-
|
|
||||||
zcompare(C, -1, I),
|
|
||||||
scalar_mult_(C, Curve, K, I, R0-R).
|
|
||||||
|
|
||||||
scalar_mult_(=, _, _, _, ml(R,_)-R).
|
|
||||||
scalar_mult_(<, Curve, K, I0, ML0-R) :-
|
|
||||||
BitSet #= K /\ (1 << I0),
|
|
||||||
zcompare(C, 0, BitSet),
|
|
||||||
montgomery_step(C, Curve, ML0, ML1),
|
|
||||||
I1 #= I0 - 1,
|
|
||||||
scalar_multiplication(Curve, K, I1, ML1-R).
|
|
||||||
|
|
||||||
montgomery_step(=, Curve, ml(R0,S0), ml(R,S)) :-
|
|
||||||
curve_points_addition(Curve, R0, S0, S),
|
|
||||||
curve_point_double(Curve, R0, R).
|
|
||||||
montgomery_step(<, Curve, ml(R0,S0), ml(R,S)) :-
|
|
||||||
curve_points_addition(Curve, R0, S0, R),
|
|
||||||
curve_point_double(Curve, S0, S).
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
Doubling a point: R = A + A.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
curve_point_double(_, null, null).
|
|
||||||
curve_point_double(Curve, point(AX,AY), R) :-
|
|
||||||
curve_p(Curve, P),
|
|
||||||
curve_a(Curve, A),
|
|
||||||
Numerator #= (3*AX^2 + A) mod P,
|
|
||||||
Denom0 #= 2*AY mod P,
|
|
||||||
multiplicative_inverse_modulo_p(Denom0, P, Denom),
|
|
||||||
S #= (Numerator*Denom) mod P,
|
|
||||||
R = point(RX,RY),
|
|
||||||
RX #= (S^2 - 2*AX) mod P,
|
|
||||||
RY #= (S*(AX - RX) - AY) mod P,
|
|
||||||
must_be_on_curve(Curve, R).
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
Adding two points.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
curve_points_addition(Curve, P, Q, R) :-
|
|
||||||
curve_points_addition_(P, Curve, Q, R).
|
|
||||||
|
|
||||||
curve_points_addition_(null, _, P, P).
|
|
||||||
curve_points_addition_(P, _, null, P).
|
|
||||||
curve_points_addition_(point(AX,AY), Curve, point(BX,BY), R) :-
|
|
||||||
curve_p(Curve, P),
|
|
||||||
Numerator #= (AY - BY) mod P,
|
|
||||||
Denom0 #= (AX - BX) mod P,
|
|
||||||
multiplicative_inverse_modulo_p(Denom0, P, Denom),
|
|
||||||
S #= (Numerator * Denom) mod P,
|
|
||||||
R = point(RX,RY),
|
|
||||||
RX #= (S^2 - AX - BX) mod P,
|
|
||||||
RY #= (S*(AX - RX) - AY) mod P,
|
|
||||||
must_be_on_curve(Curve, R).
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Validation.
|
Validation.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
@@ -838,7 +746,7 @@ curve_contains_point(Curve, point(QX,QY)) :-
|
|||||||
|
|
||||||
must_be_on_curve(Curve, P) :-
|
must_be_on_curve(Curve, P) :-
|
||||||
\+ curve_contains_point(Curve, P),
|
\+ curve_contains_point(Curve, P),
|
||||||
throw(not_on_curve(P)).
|
domain_error(point_on_curve, P, crypto_elliptic_curves).
|
||||||
must_be_on_curve(Curve, P) :- curve_contains_point(Curve, P).
|
must_be_on_curve(Curve, P) :- curve_contains_point(Curve, P).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
@@ -855,21 +763,38 @@ must_be_on_curve(Curve, P) :- curve_contains_point(Curve, P).
|
|||||||
-text -no_seed -name secp256k1
|
-text -no_seed -name secp256k1
|
||||||
|
|
||||||
You must remove the leading "04:" from the generator.
|
You must remove the leading "04:" from the generator.
|
||||||
|
|
||||||
|
The field length depends on the order of the curve and can be computed
|
||||||
|
with order_field_length/2.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
order_field_length(Order, L) :-
|
||||||
|
fitting_exponent(Order, 0, E),
|
||||||
|
L #= (E + 7) // 8.
|
||||||
|
|
||||||
|
fitting_exponent(N, E0, E) :-
|
||||||
|
( 2^E0 #>= N -> E #= E0
|
||||||
|
; E1 #= E0 + 1,
|
||||||
|
fitting_exponent(N, E1, E)
|
||||||
|
).
|
||||||
|
|
||||||
crypto_name_curve(secp112r1,
|
crypto_name_curve(secp112r1,
|
||||||
curve(0x00db7c2abf62e35e668076bead208b,
|
curve(secp112r1,
|
||||||
|
0x00db7c2abf62e35e668076bead208b,
|
||||||
0x00db7c2abf62e35e668076bead2088,
|
0x00db7c2abf62e35e668076bead2088,
|
||||||
0x659ef8ba043916eede8911702b22,
|
0x659ef8ba043916eede8911702b22,
|
||||||
point(0x09487239995a5ee76b55f9c2f098,
|
point(0x09487239995a5ee76b55f9c2f098,
|
||||||
0xa89ce5af8724c0a23e0e0ff77500),
|
0xa89ce5af8724c0a23e0e0ff77500),
|
||||||
0x00db7c2abf62e35e7628dfac6561c5,
|
0x00db7c2abf62e35e7628dfac6561c5,
|
||||||
|
14,
|
||||||
1)).
|
1)).
|
||||||
crypto_name_curve(secp256k1,
|
crypto_name_curve(secp256k1,
|
||||||
curve(0x00fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
|
curve(secp256k1,
|
||||||
|
0x00fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
|
||||||
0x0,
|
0x0,
|
||||||
0x7,
|
0x7,
|
||||||
point(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
|
point(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
|
||||||
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8),
|
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8),
|
||||||
0x00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
|
0x00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
|
||||||
|
32,
|
||||||
1)).
|
1)).
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ use ripemd160::{Ripemd160, Digest};
|
|||||||
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
|
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
|
||||||
use blake2::{Blake2s, Blake2b};
|
use blake2::{Blake2s, Blake2b};
|
||||||
|
|
||||||
|
use openssl::ec::{EcGroup, EcPoint};
|
||||||
|
use openssl::bn::{BigNum, BigNumContext};
|
||||||
|
use openssl::nid::Nid;
|
||||||
|
|
||||||
pub fn get_key() -> KeyEvent {
|
pub fn get_key() -> KeyEvent {
|
||||||
let key;
|
let key;
|
||||||
enable_raw_mode().expect("failed to enable raw mode");
|
enable_raw_mode().expect("failed to enable raw mode");
|
||||||
@@ -5441,6 +5445,55 @@ impl MachineState {
|
|||||||
|
|
||||||
self.unify(self[temp_v!(5)], complete_string);
|
self.unify(self[temp_v!(5)], complete_string);
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::CryptoCurveScalarMult => {
|
||||||
|
let curve = match self.store(self.deref(self[temp_v!(1)])) {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
|
||||||
|
atom.as_str()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let curve_id = match curve {
|
||||||
|
"secp112r1" => { Nid::SECP112R1 }
|
||||||
|
"secp256k1" => { Nid::SECP256K1 }
|
||||||
|
_ => { unreachable!() }
|
||||||
|
};
|
||||||
|
|
||||||
|
let scalar =
|
||||||
|
match Number::try_from((self[temp_v!(2)], &self.heap)) {
|
||||||
|
Ok(Number::Fixnum(n)) => {
|
||||||
|
Integer::from(n)
|
||||||
|
}
|
||||||
|
Ok(Number::Integer(n)) => {
|
||||||
|
Integer::from(&*n.clone())
|
||||||
|
}
|
||||||
|
_ => { unreachable!() }
|
||||||
|
};
|
||||||
|
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("crypto_curve_scalar_mult"), 5);
|
||||||
|
let qbytes = self.integers_to_bytevec(temp_v!(3), stub);
|
||||||
|
|
||||||
|
let mut bnctx = BigNumContext::new().unwrap();
|
||||||
|
let group = EcGroup::from_curve_name(curve_id).unwrap();
|
||||||
|
let mut point = EcPoint::from_bytes(&group, &qbytes, &mut bnctx).unwrap();
|
||||||
|
let scalar_bn = BigNum::from_dec_str(&scalar.to_string()).unwrap();
|
||||||
|
let mut result = EcPoint::new(&group).unwrap();
|
||||||
|
result.mul(&group, &mut point, &scalar_bn, &mut bnctx).ok();
|
||||||
|
|
||||||
|
let mut rx = BigNum::new().unwrap();
|
||||||
|
let mut ry = BigNum::new().unwrap();
|
||||||
|
result.affine_coordinates_gfp(&group, &mut rx, &mut ry, &mut bnctx).ok();
|
||||||
|
let sx = self.heap.put_complete_string(&rx.to_dec_str().unwrap().to_string());
|
||||||
|
let sy = self.heap.put_complete_string(&ry.to_dec_str().unwrap().to_string());
|
||||||
|
|
||||||
|
self.unify(self[temp_v!(4)], sx);
|
||||||
|
self.unify(self[temp_v!(5)], sy);
|
||||||
|
}
|
||||||
&SystemClauseType::Ed25519NewKeyPair => {
|
&SystemClauseType::Ed25519NewKeyPair => {
|
||||||
let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap();
|
let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap();
|
||||||
let complete_string = {
|
let complete_string = {
|
||||||
|
|||||||
Reference in New Issue
Block a user