comparison NaCl/APIv2.cs @ 73:6aca18ee4ec6

NaCl: improved ed25519 implementation, added simple API for ed25519 and sha512
author Ivo Smits <Ivo@UCIS.nl>
date Sat, 02 Nov 2013 16:01:09 +0100
parents 29cf42a12c34
children 4714531734b3
comparison
equal deleted inserted replaced
72:b7d981ccd434 73:6aca18ee4ec6
2 using System.Globalization; 2 using System.Globalization;
3 using UCIS.Util; 3 using UCIS.Util;
4 using curve25519xsalsa20poly1305impl = UCIS.NaCl.crypto_box.curve25519xsalsa20poly1305; 4 using curve25519xsalsa20poly1305impl = UCIS.NaCl.crypto_box.curve25519xsalsa20poly1305;
5 using edwards25519sha512batchimpl = UCIS.NaCl.crypto_sign.edwards25519sha512batch; 5 using edwards25519sha512batchimpl = UCIS.NaCl.crypto_sign.edwards25519sha512batch;
6 using xsalsa20poly1305impl = UCIS.NaCl.crypto_secretbox.xsalsa20poly1305; 6 using xsalsa20poly1305impl = UCIS.NaCl.crypto_secretbox.xsalsa20poly1305;
7 using sha512impl = UCIS.NaCl.crypto_hash.sha512;
8 using ed25519impl = UCIS.NaCl.crypto_sign.ed25519;
7 9
8 namespace UCIS.NaCl.v2 { 10 namespace UCIS.NaCl.v2 {
9 public class curve25519keypair { 11 public class curve25519keypair {
10 private Byte[] secretkey; 12 private Byte[] secretkey;
11 private Byte[] publickey = null; 13 private Byte[] publickey = null;
206 public xsalsa20poly1305 Clone() { 208 public xsalsa20poly1305 Clone() {
207 return new xsalsa20poly1305(sharedkey, nonce); 209 return new xsalsa20poly1305(sharedkey, nonce);
208 } 210 }
209 } 211 }
210 public class edwards25519sha512batch { 212 public class edwards25519sha512batch {
211 public Byte[] Sign(Byte[] message, Byte[] secretkey) { 213 public static Byte[] Sign(Byte[] message, Byte[] secretkey) {
212 return edwards25519sha512batchimpl.crypto_sign(message, secretkey); 214 return edwards25519sha512batchimpl.crypto_sign(message, secretkey);
213 } 215 }
214 public int GetSignedSize(int size) { 216 public static int GetSignedSize(int size) {
215 return size + 64; 217 return size + 64;
216 } 218 }
217 public Byte[] Open(Byte[] signed, Byte[] publickey) { 219 public static Byte[] Open(Byte[] signed, Byte[] publickey) {
218 return edwards25519sha512batchimpl.crypto_sign_open(signed, publickey); 220 return edwards25519sha512batchimpl.crypto_sign_open(signed, publickey);
219 } 221 }
220 public unsafe Boolean Verify(Byte[] signed, Byte[] publickey) { 222 public static unsafe Boolean Verify(Byte[] signed, Byte[] publickey) {
221 if (publickey.Length != edwards25519sha512batchimpl.PUBLICKEYBYTES) throw new ArgumentException("publickey.Length != PUBLICKEYBYTES"); 223 if (publickey.Length != edwards25519sha512batchimpl.PUBLICKEYBYTES) throw new ArgumentException("publickey.Length != PUBLICKEYBYTES");
222 UInt64 mlen; 224 UInt64 mlen;
223 fixed (Byte* smp = signed, pkp = publickey) return edwards25519sha512batchimpl.crypto_sign_open(null, out mlen, smp, (ulong)signed.Length, pkp) == 0; 225 fixed (Byte* smp = signed, pkp = publickey) return edwards25519sha512batchimpl.crypto_sign_open(null, out mlen, smp, (ulong)signed.Length, pkp) == 0;
224 } 226 }
225 public Byte[] Extract(Byte[] signed) { 227 public static Byte[] Extract(Byte[] signed) {
226 if (signed.Length < 64) return null; 228 if (signed.Length < 64) return null;
227 Byte[] ret = new Byte[signed.Length - 64]; 229 Byte[] ret = new Byte[signed.Length - 64];
228 Buffer.BlockCopy(signed, 32, ret, 0, ret.Length); 230 Buffer.BlockCopy(signed, 32, ret, 0, ret.Length);
229 return ret; 231 return ret;
230 } 232 }
231 public int GetExtractedSize(int size) { 233 public static int GetExtractedSize(int size) {
232 if (size < 64) return -1; 234 if (size < 64) return -1;
233 return size - 64; 235 return size - 64;
234 } 236 }
235 } 237 }
238 public class sha512 {
239 sha512impl.sha512state state = new sha512impl.sha512state();
240 public sha512() {
241 state.init();
242 }
243 public unsafe void Process(Byte[] buffer, int offset, int count) {
244 if (offset < 0 || count < 0 || offset + count > buffer.Length) throw new ArgumentException("buffer");
245 fixed (Byte* p = buffer) state.process(p + offset, count);
246 }
247 public unsafe void GetHash(Byte[] hash, int offset) {
248 if (offset < 0 || offset + 64 > hash.Length) throw new ArgumentException("hash");
249 fixed (Byte* p = hash) state.finish(p + offset);
250 }
251 public unsafe Byte[] GetHash() {
252 Byte[] hash = new Byte[64];
253 GetHash(hash, 0);
254 return hash;
255 }
256 public static unsafe void GetHash(Byte[] buffer, int offset, int count, Byte[] hash, int hashoffset) {
257 if (offset < 0 || offset + count > buffer.Length) throw new ArgumentException("buffer");
258 if (offset < 0 || offset + 64 > hash.Length) throw new ArgumentException("hash");
259 sha512impl.sha512state state = new sha512impl.sha512state();
260 state.init();
261 fixed (Byte* p = buffer) state.process(p + offset, count);
262 fixed (Byte* p = hash) state.finish(p + offset);
263 }
264 public static unsafe Byte[] GetHash(Byte[] buffer, int offset, int count) {
265 Byte[] hash = new Byte[64];
266 GetHash(buffer,offset,count,hash,0);
267 return hash;
268 }
269 }
270 public class ed25519keypair {
271 internal Byte[] key;
272
273 public ed25519keypair() {
274 Byte[] pk;
275 ed25519impl.crypto_sign_keypair(out pk, out key);
276 }
277 public ed25519keypair(Byte[] key) {
278 if (key.Length == 64) {
279 this.key = ArrayUtil.ToArray(key);
280 }else {
281 Byte[] pk;
282 ed25519impl.crypto_sign_seed_keypair(out pk, out this.key, key);
283 }
284 }
285 public ed25519keypair(String key) : this(curve25519keypair.DecodeHexString(key, key.Length)) { }
286 public Byte[] PublicKey { get { return ArrayUtil.Slice(key, 32, 32); } }
287 public Byte[] SecretKey { get { return ArrayUtil.Slice(key, 0, 32); } }
288 public Byte[] ExpandedKey { get { return ArrayUtil.ToArray(key); } }
289
290 public Byte[] GetSignature(Byte[] message) {
291 return ed25519.GetSignature(message, key);
292 }
293 public Byte[] GetSignature(Byte[] message, int offset, int count) {
294 return ed25519.GetSignature(new ArraySegment<Byte>(message, offset, count), key);
295 }
296 public Byte[] SignMessage(Byte[] message) {
297 return ed25519.SignMessage(message, key);
298 }
299 }
300 public class ed25519 {
301 public static unsafe Byte[] GetSignature(Byte[] message, Byte[] key) {
302 if (message == null) throw new ArgumentNullException("message");
303 if (key.Length != 64) throw new ArgumentException("key");
304 Byte[] sig = new Byte[64];
305 fixed (Byte* sigp = sig, msgp = message, kp = key) ed25519impl.crypto_getsignature(sigp, msgp, message.Length, kp);
306 return sig;
307 }
308 public static unsafe Byte[] GetSignature(ArraySegment<Byte> message, Byte[] key) {
309 if (message == null) throw new ArgumentNullException("message");
310 if (key.Length != 64) throw new ArgumentException("key");
311 if (message.Offset < 0 || message.Count < 0 || message.Offset + message.Count > message.Array.Length) throw new ArgumentException("message");
312 Byte[] sig = new Byte[64];
313 fixed (Byte* sigp = sig, msgp = message.Array, kp = key) ed25519impl.crypto_getsignature(sigp, msgp + message.Offset, message.Count, kp);
314 return sig;
315 }
316 public static unsafe Byte[] SignMessage(Byte[] message, Byte[] key) {
317 if (key.Length != 64) throw new ArgumentException("key");
318 Byte[] ret = new Byte[message.Length + 64];
319 int smlen;
320 fixed (Byte* sm = ret, msgp = message, kp = key) ed25519impl.crypto_sign(sm, out smlen, msgp, message.Length, kp);
321 return ret;
322 }
323 public static unsafe Boolean VerifySignature(Byte[] message, Byte[] signature, Byte[] pk) {
324 if (signature.Length < 64) throw new ArgumentException("signature");
325 if (pk.Length < 32) throw new ArgumentException("pk");
326 fixed (Byte* sp = signature, mp = message, kp = pk) return ed25519impl.crypto_sign_verify(sp, mp, message.Length, kp);
327 }
328 public static unsafe Boolean VerifySignature(ArraySegment<Byte> message, ArraySegment<Byte> signature, Byte[] pk) {
329 if (signature.Offset < 0 || signature.Count < 64 || signature.Offset + signature.Count < signature.Array.Length) throw new ArgumentException("signature");
330 if (message.Offset < 0 || message.Count < 0 || message.Offset + message.Count < message.Array.Length) throw new ArgumentException("message");
331 if (pk.Length < 32) throw new ArgumentException("pk");
332 fixed (Byte* sp = signature.Array, mp = message.Array, kp = pk) return ed25519impl.crypto_sign_verify(sp + signature.Offset, mp + message.Offset, message.Count, kp);
333 }
334 public static unsafe Boolean VerifySignedMessage(Byte[] signedmessage, Byte[] pk) {
335 if (signedmessage.Length < 64) throw new ArgumentException("signedmessage");
336 if (pk.Length < 32) throw new ArgumentException("pk");
337 fixed (Byte* mp = signedmessage, kp = pk) return ed25519impl.crypto_sign_verify(mp, mp + 64, signedmessage.Length - 64, kp);
338 }
339 public static Byte[] ExtractSignedMessage(Byte[] signedmessage) {
340 return ArrayUtil.Slice(signedmessage, 64);
341 }
342 public static Byte[] ExtractSignedMessage(ArraySegment<Byte> signedmessage) {
343 return ArrayUtil.Slice(signedmessage.Array, signedmessage.Offset + 64, signedmessage.Count - 64);
344 }
345 public static ArraySegment<Byte> ExtractSignedMessageFast(Byte[] signedmessage) {
346 return new ArraySegment<Byte>(signedmessage, 64, signedmessage.Length - 64);
347 }
348 public static ArraySegment<Byte> ExtractSignedMessageFast(ArraySegment<Byte> signedmessage) {
349 return new ArraySegment<Byte>(signedmessage.Array, signedmessage.Offset + 64, signedmessage.Count - 64);
350 }
351 public static Byte[] OpenSignedMessage(Byte[] signedmessage, Byte[] pk) {
352 if (!VerifySignedMessage(signedmessage, pk)) return null;
353 return ExtractSignedMessage(signedmessage);
354 }
355 }
236 } 356 }