# HG changeset patch # User Ivo Smits # Date 1369321337 -7200 # Node ID 29cf42a12c349237ff7fd6fe63ca04d04ff05f10 # Parent aedd0e4adef74f5c3fd04261e7e5231c172dcf9b Added convenience functions in NaCl API and ArrayUtils diff -r aedd0e4adef7 -r 29cf42a12c34 NaCl/APIv2.cs --- a/NaCl/APIv2.cs Wed May 01 23:44:43 2013 +0200 +++ b/NaCl/APIv2.cs Thu May 23 17:02:17 2013 +0200 @@ -1,53 +1,79 @@ using System; +using System.Globalization; +using UCIS.Util; using curve25519xsalsa20poly1305impl = UCIS.NaCl.crypto_box.curve25519xsalsa20poly1305; using edwards25519sha512batchimpl = UCIS.NaCl.crypto_sign.edwards25519sha512batch; using xsalsa20poly1305impl = UCIS.NaCl.crypto_secretbox.xsalsa20poly1305; namespace UCIS.NaCl.v2 { public class curve25519keypair { - private Byte[] publickey, secretkey; + private Byte[] secretkey; + private Byte[] publickey = null; public curve25519keypair() { curve25519xsalsa20poly1305impl.crypto_box_keypair(out publickey, out secretkey); } public curve25519keypair(Byte[] secretkey) { - this.publickey = curve25519xsalsa20poly1305impl.crypto_box_getpublickey(secretkey); this.secretkey = secretkey; } + public curve25519keypair(String secretkey) { + this.secretkey = DecodeHexString(secretkey, curve25519xsalsa20poly1305impl.SECRETKEYBYTES); + } public curve25519keypair(Byte[] secretkey, Byte[] publickey) { if (publickey.Length != curve25519xsalsa20poly1305impl.PUBLICKEYBYTES) throw new ArgumentOutOfRangeException("publickey"); if (secretkey.Length != curve25519xsalsa20poly1305impl.SECRETKEYBYTES) throw new ArgumentOutOfRangeException("secretkey"); this.secretkey = secretkey; this.publickey = publickey; } - public Byte[] PublicKey { get { return publickey; } } + public Byte[] PublicKey { + get { + if (publickey == null) publickey = curve25519xsalsa20poly1305impl.crypto_box_getpublickey(secretkey); + return publickey; + } + } public Byte[] SecretKey { get { return secretkey; } } + internal static Byte[] DecodeHexString(String str, int length) { + if (str.Length != length * 2) throw new ArgumentException("str", "Incorrect key length"); + Byte[] bytes = new Byte[length]; + for (int i = 0; i < length; i++) bytes[i] = Byte.Parse(str.Substring(i * 2, 2), NumberStyles.HexNumber); + return bytes; + } } public class curve25519xsalsa20poly1305 : xsalsa20poly1305 { - public curve25519xsalsa20poly1305(Byte[] publickey, curve25519keypair secretkey) - : this(publickey, secretkey.SecretKey) { + public Byte[] PublicKey { get; private set; } + public curve25519keypair SecretKey { get; private set; } + public curve25519xsalsa20poly1305(String publickey, String secretkey) + : this(curve25519keypair.DecodeHexString(publickey, curve25519xsalsa20poly1305impl.PUBLICKEYBYTES), new curve25519keypair(secretkey)) { } public curve25519xsalsa20poly1305(Byte[] publickey, Byte[] secretkey) - : base(curve25519xsalsa20poly1305impl.crypto_box_beforenm(publickey, secretkey)) { + : this(publickey, new curve25519keypair(secretkey)) { + } + public curve25519xsalsa20poly1305(Byte[] publickey, curve25519keypair secretkey) + : base(curve25519xsalsa20poly1305impl.crypto_box_beforenm(publickey, secretkey.SecretKey)) { + this.PublicKey = publickey; + this.SecretKey = secretkey; } } public class xsalsa20poly1305 { - Byte[] sharedkey; - Byte[] nonce; + protected Byte[] sharedkey = new Byte[xsalsa20poly1305impl.KEYBYTES]; + Byte[] nonce = new Byte[xsalsa20poly1305impl.NONCEBYTES]; public int SharedKeySize { get { return xsalsa20poly1305impl.KEYBYTES; } } public xsalsa20poly1305(Byte[] sharedkey) : this(sharedkey, null) { } public xsalsa20poly1305(Byte[] sharedkey, Byte[] nonce) { - if (ReferenceEquals(sharedkey, null)) throw new ArgumentNullException("secretkey"); + if (sharedkey == null) throw new ArgumentNullException("secretkey"); if (sharedkey.Length != xsalsa20poly1305impl.KEYBYTES) throw new ArgumentOutOfRangeException("secretkey", "The key size does not match the expected key length"); - this.sharedkey = sharedkey; - this.nonce = new Byte[xsalsa20poly1305impl.NONCEBYTES]; - if (!ReferenceEquals(nonce, null)) this.Nonce = nonce; + sharedkey.CopyTo(this.sharedkey, 0); + if (nonce != null) this.Nonce = nonce; } public Byte[] Nonce { get { return this.nonce; } + set { NonceValue = value; } + } + public Byte[] NonceValue { + get { return ArrayUtil.ToArray(nonce); } set { if (ReferenceEquals(value, null)) throw new ArgumentNullException("value"); if (value.Length > xsalsa20poly1305impl.NONCEBYTES) throw new ArgumentOutOfRangeException("value", "Nonce is too big"); @@ -55,6 +81,14 @@ Array.Clear(this.nonce, value.Length, this.nonce.Length - value.Length); } } + public Byte[] NonceBuffer { + get { return this.nonce; } + set { + if (ReferenceEquals(value, null)) throw new ArgumentNullException("value"); + if (value.Length > xsalsa20poly1305impl.NONCEBYTES) throw new ArgumentOutOfRangeException("value", "Incorrect nonce length"); + this.nonce = value; + } + } public Byte[] SharedKey { get { return sharedkey; } diff -r aedd0e4adef7 -r 29cf42a12c34 Util/ArrayUtil.cs --- a/Util/ArrayUtil.cs Wed May 01 23:44:43 2013 +0200 +++ b/Util/ArrayUtil.cs Thu May 23 17:02:17 2013 +0200 @@ -22,6 +22,9 @@ public static T[] ToArray(ArraySegment input) { return Slice(input.Array, input.Offset, input.Count); } + public static T[] ToArray(T[] input) { + return (T[])input.Clone(); + } public static IList ToList(IEnumerable input) { return new List(input); }