1 module sign; 2 3 extern (C) { 4 int crypto_sign_keypair(ref ubyte[32] pk, ref ubyte[64] sk); 5 int crypto_sign(ubyte *sm, ulong *smlen, ubyte *m, ulong mlen, ref ubyte[64] sk); 6 int crypto_sign_open(ubyte *m, ulong *mlen, ubyte *sm, ulong smlen, ref ubyte[32] pk); 7 size_t crypto_sign_bytes(); 8 } 9 10 struct SignedMessage { 11 ubyte[] data; 12 13 // signedBy returns true if this messages was signed by the keypair, signer. 14 bool signedBy(SignKeyPair signer) { 15 ubyte[] output = new ubyte[this.data.length - crypto_sign_bytes()]; 16 ulong length; 17 int valid = crypto_sign_open(&output[0], &length, &this.data[0], this.data.length, signer.public_key); 18 return (valid == 0); 19 } 20 } 21 22 class SignKeyPair { 23 ubyte[32] public_key; 24 ubyte[64] secret_key; 25 26 this() { 27 assert(crypto_sign_keypair(this.public_key, this.secret_key) == 0); 28 } 29 30 this(ubyte[32] pubk, ubyte[64] secretk) { 31 this.public_key = pubk; 32 this.secret_key = secretk; 33 } 34 35 SignedMessage sign(string data) { 36 return this.sign(cast(ubyte[])data); 37 } 38 39 SignedMessage sign(ubyte[] data) { 40 ubyte[] output = new ubyte[data.length + crypto_sign_bytes()]; 41 ulong length; 42 assert(crypto_sign(&output[0], &length, &data[0], data.length, this.secret_key) == 0); 43 return SignedMessage(output); 44 } 45 } 46 47 48 unittest { 49 auto bob = new SignKeyPair; 50 auto alice = new SignKeyPair; 51 52 // Test that key signing works 53 SignedMessage data = bob.sign("hey alice this is bob!"); 54 assert(data.signedBy(bob)); 55 assert(!data.signedBy(alice)); 56 } 57