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); } } }