use super::crypto_sign_ed25519::*;
pub use super::crypto_sign_ed25519::{PublicKey, SecretKey};
use crate::constants::CRYPTO_SIGN_BYTES;
use crate::error::Error;
pub fn crypto_sign_keypair_inplace(public_key: &mut PublicKey, secret_key: &mut SecretKey) {
crypto_sign_ed25519_keypair_inplace(public_key, secret_key)
}
pub fn crypto_sign_seed_keypair_inplace(
public_key: &mut PublicKey,
secret_key: &mut SecretKey,
seed: &[u8; 32],
) {
crypto_sign_ed25519_seed_keypair_inplace(public_key, secret_key, seed)
}
pub fn crypto_sign_keypair() -> (PublicKey, SecretKey) {
crypto_sign_ed25519_keypair()
}
pub fn crypto_sign_seed_keypair(seed: &[u8; 32]) -> (PublicKey, SecretKey) {
crypto_sign_ed25519_seed_keypair(seed)
}
pub fn crypto_sign(
signed_message: &mut [u8],
message: &[u8],
secret_key: &SecretKey,
) -> Result<(), Error> {
if signed_message.len() != message.len() + CRYPTO_SIGN_BYTES {
Err(dryoc_error!(format!(
"signed_message length incorrect (expect {}, got {})",
message.len() + CRYPTO_SIGN_BYTES,
signed_message.len()
)))
} else {
crypto_sign_ed25519(signed_message, message, secret_key)
}
}
pub fn crypto_sign_open(
message: &mut [u8],
signed_message: &[u8],
public_key: &PublicKey,
) -> Result<(), Error> {
if signed_message.len() < CRYPTO_SIGN_BYTES {
Err(dryoc_error!(format!(
"signed_message length invalid ({} < {})",
signed_message.len(),
CRYPTO_SIGN_BYTES,
)))
} else if message.len() != signed_message.len() - CRYPTO_SIGN_BYTES {
Err(dryoc_error!(format!(
"message length incorrect (expect {}, got {})",
signed_message.len() - CRYPTO_SIGN_BYTES,
message.len()
)))
} else {
crypto_sign_ed25519_open(message, signed_message, public_key)
}
}
pub fn crypto_sign_detached(
signature: &mut Signature,
message: &[u8],
secret_key: &SecretKey,
) -> Result<(), Error> {
crypto_sign_ed25519_detached(signature, message, secret_key)
}
pub fn crypto_sign_verify_detached(
signature: &Signature,
message: &[u8],
public_key: &PublicKey,
) -> Result<(), Error> {
crypto_sign_ed25519_verify_detached(signature, message, public_key)
}
pub struct SignerState {
state: Ed25519SignerState,
}
pub fn crypto_sign_init() -> SignerState {
SignerState {
state: crypto_sign_ed25519ph_init(),
}
}
pub fn crypto_sign_update(state: &mut SignerState, message: &[u8]) {
crypto_sign_ed25519ph_update(&mut state.state, message)
}
pub fn crypto_sign_final_create(
state: SignerState,
signature: &mut Signature,
secret_key: &SecretKey,
) -> Result<(), Error> {
crypto_sign_ed25519ph_final_create(state.state, signature, secret_key)
}
pub fn crypto_sign_final_verify(
state: SignerState,
signature: &Signature,
public_key: &PublicKey,
) -> Result<(), Error> {
crypto_sign_ed25519ph_final_verify(state.state, signature, public_key)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_crypto_sign() {
use base64::Engine as _;
use base64::engine::general_purpose;
use sodiumoxide::crypto::sign;
for _ in 0..10 {
let (public_key, secret_key) = crypto_sign_keypair();
let message = b"important message";
let mut signed_message = vec![0u8; message.len() + CRYPTO_SIGN_BYTES];
crypto_sign(&mut signed_message, message, &secret_key).expect("sign failed");
let so_signed_message = sign::sign(
message,
&sign::SecretKey::from_slice(&secret_key).expect("secret key failed"),
);
assert_eq!(
general_purpose::STANDARD.encode(&signed_message),
general_purpose::STANDARD.encode(&so_signed_message)
);
let so_m = sign::verify(
&signed_message,
&sign::PublicKey::from_slice(&public_key).expect("public key failed"),
)
.expect("verify failed");
assert_eq!(so_m, message);
}
}
#[test]
fn test_crypto_sign_open() {
use base64::Engine as _;
use base64::engine::general_purpose;
use sodiumoxide::crypto::sign;
for _ in 0..10 {
let (public_key, secret_key) = crypto_sign_keypair();
let message = b"important message";
let mut signed_message = vec![0u8; message.len() + CRYPTO_SIGN_BYTES];
crypto_sign(&mut signed_message, message, &secret_key).expect("sign failed");
let so_signed_message = sign::sign(
message,
&sign::SecretKey::from_slice(&secret_key).expect("secret key failed"),
);
assert_eq!(
general_purpose::STANDARD.encode(&signed_message),
general_purpose::STANDARD.encode(&so_signed_message)
);
let so_m = sign::verify(
&signed_message,
&sign::PublicKey::from_slice(&public_key).expect("public key failed"),
)
.expect("verify failed");
assert_eq!(so_m, message);
let mut opened_message = vec![0u8; message.len()];
crypto_sign_open(&mut opened_message, &signed_message, &public_key)
.expect("verify failed");
assert_eq!(opened_message, message);
}
}
#[test]
fn test_crypto_sign_detached() {
use sodiumoxide::crypto::sign;
for _ in 0..10 {
let (public_key, secret_key) = crypto_sign_keypair();
let message = b"important message";
let mut signature = [0u8; CRYPTO_SIGN_BYTES];
crypto_sign_detached(&mut signature, message, &secret_key).expect("sign failed");
assert!(sign::verify_detached(
&sign::ed25519::Signature::from_bytes(&signature).expect("secret key failed"),
message,
&sign::PublicKey::from_slice(&public_key).expect("public key failed"),
));
crypto_sign_verify_detached(&signature, message, &public_key).expect("verify failed");
}
}
#[test]
fn test_crypto_sign_incremental() {
use sodiumoxide::crypto::sign;
use crate::rng::copy_randombytes;
for _ in 0..10 {
let (public_key, secret_key) = crypto_sign_keypair();
let mut signer = crypto_sign_init();
let mut verifier = crypto_sign_init();
let mut so_signer = sign::State::init();
let mut so_verifier = sign::State::init();
for _ in 0..3 {
let mut randos = vec![0u8; 100];
copy_randombytes(&mut randos);
crypto_sign_update(&mut signer, &randos);
crypto_sign_update(&mut verifier, &randos);
so_signer.update(&randos);
so_verifier.update(&randos);
}
let mut signature = [0u8; CRYPTO_SIGN_BYTES];
crypto_sign_final_create(signer, &mut signature, &secret_key)
.expect("final create failed");
let so_signature = so_signer
.finalize(&sign::SecretKey::from_slice(&secret_key).expect("secret key failed"));
assert_eq!(signature, so_signature.to_bytes());
crypto_sign_final_verify(verifier, &so_signature.to_bytes(), &public_key)
.expect("verify failed");
assert!(so_signer.verify(
&sign::ed25519::Signature::from_bytes(&signature).expect("secret key failed"),
&sign::PublicKey::from_slice(&public_key).expect("public key failed"),
));
}
}
}