using System;
using Framework.Cryptography.Ed25519.Internal.Ed25519Ref10;
using System.Diagnostics.Contracts;
namespace Framework.Cryptography.Ed25519
{
public static class Ed25519
{
///
/// Public Keys are 32 byte values. All possible values of this size a valid.
///
public const int PublicKeySize = 32;
///
/// Signatures are 64 byte values
///
public const int SignatureSize = 64;
///
/// Private key seeds are 32 byte arbitrary values. This is the form that should be generated and stored.
///
public const int PrivateKeySeedSize = 32;
///
/// A 64 byte expanded form of private key. This form is used internally to improve performance
///
public const int ExpandedPrivateKeySize = 32 * 2;
///
/// Verify Ed25519 signature
///
/// Signature bytes
/// Message
/// Public key
/// True if signature is valid, false if it's not
public static bool Verify(ArraySegment signature, ArraySegment message, ArraySegment publicKey, int phflag = -1, byte[] ctx = null)
{
return Ed25519Operations.crypto_sign_verify(signature.Array, signature.Offset, message.Array, message.Offset, message.Count, publicKey.Array, publicKey.Offset, phflag, ctx);
}
///
/// Verify Ed25519 signature
///
/// Signature bytes
/// Message
/// Public key
/// True if signature is valid, false if it's not
public static bool Verify(byte[] signature, byte[] message, byte[] publicKey, int phflag = -1, byte[] ctx = null)
{
return Ed25519Operations.crypto_sign_verify(signature, 0, message, 0, message.Length, publicKey, 0, phflag, ctx);
}
///
/// Create new Ed25519 signature
///
/// Buffer for signature
/// Message bytes
/// Expanded form of private key
public static void Sign(ArraySegment signature, ArraySegment message, ArraySegment expandedPrivateKey, int phflag = -1, byte[] ctx = null)
{
Ed25519Operations.crypto_sign(signature.Array, signature.Offset, message.Array, message.Offset, message.Count, expandedPrivateKey.Array, expandedPrivateKey.Offset, phflag, ctx);
}
///
/// Create new Ed25519 signature
///
/// Buffer for signature
/// Message bytes
/// Expanded form of private key
public static byte[] Sign(byte[] message, byte[] expandedPrivateKey, int phflag = -1, byte[] ctx = null)
{
var signature = new byte[SignatureSize];
Sign(new ArraySegment(signature), new ArraySegment(message), new ArraySegment(expandedPrivateKey), phflag, ctx);
return signature;
}
///
/// Calculate public key from private key seed
///
/// Private key seed value
///
public static byte[] PublicKeyFromSeed(byte[] privateKeySeed)
{
byte[] privateKey;
byte[] publicKey;
KeyPairFromSeed(out publicKey, out privateKey, privateKeySeed);
CryptoBytes.Wipe(privateKey);
return publicKey;
}
///
/// Calculate expanded form of private key from the key seed.
///
/// Private key seed value
/// Expanded form of the private key
public static byte[] ExpandedPrivateKeyFromSeed(byte[] privateKeySeed)
{
byte[] privateKey;
byte[] publicKey;
KeyPairFromSeed(out publicKey, out privateKey, privateKeySeed);
CryptoBytes.Wipe(publicKey);
return privateKey;
}
///
/// Calculate key pair from the key seed.
///
/// Public key
/// Expanded form of the private key
/// Private key seed value
public static void KeyPairFromSeed(out byte[] publicKey, out byte[] expandedPrivateKey, byte[] privateKeySeed)
{
var pk = new byte[PublicKeySize];
var sk = new byte[ExpandedPrivateKeySize];
Ed25519Operations.crypto_sign_keypair(pk, 0, sk, 0, privateKeySeed, 0);
publicKey = pk;
expandedPrivateKey = sk;
}
///
/// Calculate key pair from the key seed.
///
/// Public key
/// Expanded form of the private key
/// Private key seed value
public static void KeyPairFromSeed(ArraySegment publicKey, ArraySegment expandedPrivateKey, ArraySegment privateKeySeed)
{
Ed25519Operations.crypto_sign_keypair(
publicKey.Array, publicKey.Offset,
expandedPrivateKey.Array, expandedPrivateKey.Offset,
privateKeySeed.Array, privateKeySeed.Offset);
}
}
}