Ed25519Verify,
Ed25519NewKeyPair,
Ed25519KeyPairPublicKey,
+ Curve25519ScalarMult,
LoadHTML,
LoadXML,
GetEnv,
&SystemClauseType::Ed25519Verify => clause_name!("$ed25519_verify"),
&SystemClauseType::Ed25519NewKeyPair => clause_name!("$ed25519_new_keypair"),
&SystemClauseType::Ed25519KeyPairPublicKey => clause_name!("$ed25519_keypair_public_key"),
+ &SystemClauseType::Curve25519ScalarMult => clause_name!("$curve25519_scalar_mult"),
&SystemClauseType::LoadHTML => clause_name!("$load_html"),
&SystemClauseType::LoadXML => clause_name!("$load_xml"),
&SystemClauseType::GetEnv => clause_name!("$getenv"),
("$ed25519_verify", 5) => Some(SystemClauseType::Ed25519Verify),
("$ed25519_new_keypair", 1) => Some(SystemClauseType::Ed25519NewKeyPair),
("$ed25519_keypair_public_key", 3) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
+ ("$curve25519_scalar_mult", 3) => Some(SystemClauseType::Curve25519ScalarMult),
("$load_html", 3) => Some(SystemClauseType::LoadHTML),
("$load_xml", 3) => Some(SystemClauseType::LoadXML),
("$getenv", 2) => Some(SystemClauseType::GetEnv),
ed25519_keypair_public_key/2, % +KeyPair, +PublicKey
ed25519_sign/4, % +KeyPair, +Data, -Signature, +Options
ed25519_verify/4, % +PublicKey, +Data, +Signature, +Options
+ curve25519_generator/1, % -Generator
+ curve25519_scalar_mult/3, % +Scalar, +Point, -Result
crypto_name_curve/2, % +Name, -Curve
crypto_curve_order/2, % +Curve, -Order
crypto_curve_generator/2, % +Curve, -Generator
:- use_module(library(arithmetic)).
:- use_module(library(format)).
:- use_module(library(charsio)).
+:- use_module(library(si)).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
hex_bytes(?Hex, ?Bytes) is det.
hex_bytes(Signature0, Signature),
'$ed25519_verify'(Key, octet, Data, Encoding, Signature).
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ X25519: ECDH key exchange over Curve25519
+ =========================================
+
+ Points on Curve25519 are represented as lists of characters that denote
+ the u-coordinate of the Montgomery curve.
+
+ - curve25519_generator(-Gs)
+ Gs is the generator point of Curve25519.
+
+ - curve25519_scalar_mult(+Scalar, +Ps, -Rs)
+ Scalar must be an integer between 0 and 2^256-1,
+ or a list of 32 bytes, and Ps must be a point on the curve.
+ Computes the point Rs = Scalar*Ps as mandated by X25519.
+
+ Alice and Bob can use this to establish a shared secret as follows,
+ where Gs is the generator point of Curve25519:
+
+ 1. Alice creates a random integer a and sends As = a*Gs to Bob.
+ 2. Bob creates a random integer b and sends Bs = b*Gs to Alice.
+ 3. Alice computes Rs = a*Bs.
+ 4. Bob computes Rs = b*As.
+ 5. Alice and Bob use crypto_data_hkdf/4 on Rs with suitable
+ (same) parameters to obtain lists of bytes that can be used as
+ keys and initialization vectors for symmetric encryption.
+
+ If a and b are kept secret, this method is considered very secure.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+curve25519_generator(Gs) :-
+ length(Gs0, 32),
+ Gs0 = [9|Zs],
+ maplist(=(0), Zs),
+ maplist(char_code, Gs, Gs0).
+
+curve25519_scalar_mult(Scalar, Point, Result) :-
+ ( integer_si(Scalar) ->
+ Scalar #>= 0,
+ Scalar #< 2^256,
+ length(ScalarBytes, 32),
+ bytes_integer(ScalarBytes, Scalar)
+ ; ScalarBytes = Scalar,
+ must_be_bytes(ScalarBytes, curve25519_scalar_mult/3),
+ length(ScalarBytes, 32)
+ ),
+ maplist(char_code, Point, PointBytes),
+ '$curve25519_scalar_mult'(ScalarBytes, PointBytes, Result).
+
+bytes_integer(Bs, N) :-
+ foldl(pow, Bs, 0-0, N-_).
+
+pow(B, N0-I0, N-I) :-
+ B in 0..255,
+ N #= N0 + B*256^I0,
+ I #= I0 + 1.
+
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Operations on Elliptic Curves
=============================
crypto_curve_scalar_mult(C, Random, PublicKey, S),
crypto_curve_scalar_mult(C, PrivateKey, R, S).
+ For better security, new code should use Curve25519 instead.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
use crate::openssl::bn::{BigNum, BigNumContext};
use crate::openssl::nid::Nid;
+use sodiumoxide::crypto::scalarmult::curve25519::*;
+
use crate::native_tls::TlsConnector;
extern crate select;
_ => { self.fail = true; return Ok(()); }
}
}
+ &SystemClauseType::Curve25519ScalarMult => {
+ let stub1 = MachineError::functor_stub(clause_name!("curve25519_scalar_mult"), 3);
+ let scalar_bytes = self.integers_to_bytevec(temp_v!(1), stub1);
+ let scalar = Scalar(<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap());
+
+ let stub2 = MachineError::functor_stub(clause_name!("curve25519_scalar_mult"), 3);
+ let point_bytes = self.integers_to_bytevec(temp_v!(2), stub2);
+ let point = GroupElement(<[u8; 32]>::try_from(&point_bytes[..]).unwrap());
+
+ let result = scalarmult(&scalar, &point).unwrap();
+
+ let mut string = String::new();
+ for c in result[..].iter() {
+ string.push(*c as char);
+ }
+ let cstr = self.heap.put_complete_string(&string);
+ self.unify(self[temp_v!(3)], cstr);
+ }
&SystemClauseType::LoadHTML => {
let string = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
let doc = select::document::Document::from_read(string.as_bytes()).unwrap();