CryptoDataHKDF,
CryptoPasswordHash,
CryptoDataEncrypt,
- CryptoDataDecrypt
+ CryptoDataDecrypt,
+ Ed25519Sign,
+ Ed25519Verify
}
impl SystemClauseType {
&SystemClauseType::CryptoPasswordHash => clause_name!("$crypto_password_hash"),
&SystemClauseType::CryptoDataEncrypt => clause_name!("$crypto_data_encrypt"),
&SystemClauseType::CryptoDataDecrypt => clause_name!("$crypto_data_decrypt"),
+ &SystemClauseType::Ed25519Sign => clause_name!("$ed25519_sign"),
+ &SystemClauseType::Ed25519Verify => clause_name!("$ed25519_verify"),
}
}
("$crypto_password_hash", 4) => Some(SystemClauseType::CryptoPasswordHash),
("$crypto_data_encrypt", 5) => Some(SystemClauseType::CryptoDataEncrypt),
("$crypto_data_decrypt", 5) => Some(SystemClauseType::CryptoDataDecrypt),
+ ("$ed25519_sign", 3) => Some(SystemClauseType::Ed25519Sign),
+ ("$ed25519_verify", 3) => Some(SystemClauseType::Ed25519Verify),
_ => None,
}
}
and strings have the advantage that the atom table remains unmodified.
Especially for cryptographic applications, it as an advantage that
- using strings leaves little trace of what was processed in the system,
+ using strings leaves little trace of what was processed in the system.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- module(crypto,
crypto_password_hash/3, % +Password, -Hash, +Options
crypto_data_encrypt/6, % +PlainText, +Algorithm, +Key, +IV, -CipherText, +Options
crypto_data_decrypt/6, % +CipherText, +Algorithm, +Key, +IV, -PlainText, +Options
+ ed25519_sign/4, % +PrivateKey, +Data, -Signature, +Options
+ ed25519_verify/4, % +PublicKey, +Data, -Signature, +Options
crypto_name_curve/2, % +Name, -Curve
crypto_curve_order/2, % +Curve, -Order
crypto_curve_generator/2, % +Curve, -Generator
; domain_error(encryption_encoding, Cs, crypto)
).
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ Digital signatures with Ed25519
+ ===============================
+
+ ed25519_sign(+Key, +Data, -Signature, +Options)
+
+ Key and Data must be lists of characters. Key is a private key in
+ PKCS#8 (v1 or v2) DER format. Sign Data with Key, yielding
+ Signature as a list of hexadecimal characters.
+
+
+ ed25519_verify(+Key, +Data, +Signature, +Options)
+
+ Key and Data must be lists of characters. Key is a public key in
+ PKCS#8 DER format. Succeeds if Data was signed with the private key
+ corresponding to Key, where Signature is a list of hexadecimal
+ characters as generated by ed25519_sign/4. Fails otherwise.
+
+
+ Currently, the only option for both predicates is:
+
+ - encoding(+Encoding)
+ The default encoding of Data is utf8. The alternative is octet,
+ which treats Data as a list of raw bytes.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+ed25519_sign(Key0, Data0, Signature, Options) :-
+ options_data_bytes(Options, Data0, Data),
+ encoding_bytes(octet, Key0, Key),
+ '$ed25519_sign'(Key, Data, Signature0),
+ hex_bytes(Signature, Signature0).
+
+ed25519_verify(Key0, Data0, Signature0, Options) :-
+ options_data_bytes(Options, Data0, Data),
+ encoding_bytes(octet, Key0, Key),
+ hex_bytes(Signature0, Signature),
+ '$ed25519_verify'(Key, Data, Signature).
+
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modular multiplicative inverse.
use crate::crossterm::terminal::{enable_raw_mode, disable_raw_mode};
use ring::rand::{SecureRandom, SystemRandom};
-use ring::{digest,hkdf,pbkdf2,aead,error};
+use ring::{digest,hkdf,pbkdf2,aead,error,signature};
use ripemd160::{Ripemd160, Digest};
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
use blake2::{Blake2s, Blake2b};
self.unify(self[temp_v!(5)], complete_string);
}
+ &SystemClauseType::Ed25519Sign => {
+ let stub1 = MachineError::functor_stub(clause_name!("ed25519_sign"), 4);
+ let key = self.integers_to_bytevec(temp_v!(1), stub1);
+ let stub2 = MachineError::functor_stub(clause_name!("ed25519_sign"), 4);
+ let data = self.integers_to_bytevec(temp_v!(2), stub2);
+
+ let key_pair = match signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(&key) {
+ Ok(kp) => { kp }
+ _ => { self.fail = true; return Ok(()); }
+ };
+
+ let sig = key_pair.sign(&data);
+
+ let sig_list =
+ Addr::HeapCell(self.heap.to_list(sig.as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize)))));
+
+ self.unify(self[temp_v!(3)], sig_list);
+ }
+ &SystemClauseType::Ed25519Verify => {
+ let stub1 = MachineError::functor_stub(clause_name!("ed25519_verify"), 4);
+ let key = self.integers_to_bytevec(temp_v!(1), stub1);
+ let stub2 = MachineError::functor_stub(clause_name!("ed25519_verify"), 4);
+ let data = self.integers_to_bytevec(temp_v!(2), stub2);
+ let stub3 = MachineError::functor_stub(clause_name!("ed25519_verify"), 4);
+ let signature = self.integers_to_bytevec(temp_v!(3), stub3);
+
+ let peer_public_key = signature::UnparsedPublicKey::new(&signature::ED25519, &key);
+ match peer_public_key.verify(&data, &signature) {
+ Ok(_) => { }
+ _ => { self.fail = true; return Ok(()); }
+ }
+ }
};
return_from_clause!(self.last_call, self)