예제 #1
0
 public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey)
 {
     if (sharedKey.Array == null)
     {
         throw new ArgumentNullException("sharedKey.Array");
     }
     if (publicKey.Array == null)
     {
         throw new ArgumentNullException("publicKey.Array");
     }
     if (privateKey.Array == null)
     {
         throw new ArgumentNullException("privateKey");
     }
     if (sharedKey.Count != 32)
     {
         throw new ArgumentException("sharedKey.Count != 32");
     }
     if (publicKey.Count != 32)
     {
         throw new ArgumentException("publicKey.Count != 32");
     }
     if (privateKey.Count != 32)
     {
         throw new ArgumentException("privateKey.Count != 32");
     }
     MontgomeryOperations.scalarmult(sharedKey.Array, sharedKey.Offset, privateKey.Array, privateKey.Offset, publicKey.Array, publicKey.Offset);
     KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
 }
예제 #2
0
        /// <summary>
        /// Get a SharedSecret Key for this pair (my Private Key - your Public Key)
        /// </summary>
        /// <param name="peerPublicKey"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        public static byte[] GetSharedSecretKey(byte[] peerPublicKey, byte[] privateKey)
        {
            if (peerPublicKey == null)
            {
                throw new ArgumentNullException(nameof(peerPublicKey));
            }
            if (peerPublicKey.Length != PublicKeySizeInBytes)
            {
                throw new ArgumentException($"{nameof(peerPublicKey)} must be {PublicKeySizeInBytes}");
            }

            if (privateKey == null)
            {
                throw new ArgumentNullException(nameof(privateKey));
            }
            if (privateKey.Length != PrivateKeySizeInBytes)
            {
                throw new ArgumentException($"{nameof(privateKey)} must be {PrivateKeySizeInBytes}");
            }

            //Resolve SharedSecret Key using the Montgomery Elliptical Curve Operations...
            var sharedSecretKey = MontgomeryOperations.ScalarMultiplication(
                n: privateKey,
                p: peerPublicKey,
                qSize: SharedKeySizeInBytes);

            //hashes like the NaCl paper says instead i.e. HSalsa(x,0)
            sharedSecretKey = Salsa20.HSalsa20(key: sharedSecretKey);

            return(sharedSecretKey);
        }
예제 #3
0
        /// <summary>
        /// Handles the server DH reply message.
        /// </summary>
        /// <param name="hostKey">The host key.</param>
        /// <param name="serverExchangeValue">The server exchange value.</param>
        /// <param name="signature">The signature.</param>
        private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, byte[] signature)
        {
            _serverExchangeValue = serverExchangeValue;
            _hostKey             = hostKey;
            _signature           = signature;

            var sharedKey = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];

            MontgomeryOperations.scalarmult(sharedKey, 0, _privateKey, 0, serverExchangeValue, 0);
            SharedKey = sharedKey.ToBigInteger2().ToByteArray().Reverse();
        }
예제 #4
0
        public static byte[] CalculateSharedSecret(byte[] privKey, byte[] pubKey, bool naclCompat = false)
        {
            var key = new byte[SharedKeySizeInBytes];

            MontgomeryOperations.scalarmult(key, 0, privKey, 0, pubKey, 0);
            if (naclCompat)
            {
                KeyExchangeOutputHashNaCl(key, 0);
            }
            return(key);
        }
예제 #5
0
        public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey, bool naclCompat = false)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != SharedKeySizeInBytes)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != PublicKeySizeInBytes)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != ExpandedPrivateKeySizeInBytes)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            Curve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);

            IHash hasher = AuthenticatorFactory.CreateHashPrimitive(HashFunction.Sha512);

            hasher.BlockUpdate(privateKey.Array, privateKey.Offset, 32);
            byte[] h = new byte[64];
            hasher.DoFinal(h, 0);
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            h.SecureWipe();
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);

            if (naclCompat)
            {
                Curve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
            }
        }
예제 #6
0
        public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 64
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(privateKey.Array, privateKey.Offset, 32);
            byte[] h = hasher.Finish();
            //byte[] h = Sha512.Hash(privateKey.Array, privateKey.Offset, 32);//ToDo: Remove alloc
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);
            MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
        }
예제 #7
0
 public static void KeyExchange(Span <byte> sharedKey, ReadOnlySpan <byte> publicKey, ReadOnlySpan <byte> privateKey)
 {
     if (sharedKey.Length != 32)
     {
         throw new ArgumentException("sharedKey.Count != 32");
     }
     if (publicKey.Length != 32)
     {
         throw new ArgumentException("publicKey.Count != 32");
     }
     if (privateKey.Length != 32)
     {
         throw new ArgumentException("privateKey.Count != 32");
     }
     MontgomeryOperations.scalarmult(sharedKey, privateKey, publicKey);
     //KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset); XXX
 }
예제 #8
0
        public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
            var hasher = Blake2Fast.Blake2b.CreateIncrementalHasher(64);

            hasher.Update(new ArraySegment <byte>(privateKey.Array, privateKey.Offset, 32));
            byte[] h = hasher.Finish();
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);
            MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
        }
예제 #9
0
        public static void KeyExchange(ArraySegment \ \ sharedKey, ArraySegment \ \ publicKey, ArraySegment \ \ privateKey)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
            byte[] h = Sha512.Hash(privateKey.Array, privateKey.Offset, 32);//ToDo: Remove alloc
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);
            MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
        }
예제 #10
0
        /// <summary>
        /// Starts key exchange algorithm
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="message">Key exchange init message.</param>
        public override void Start(Session session, KeyExchangeInitMessage message)
        {
            base.Start(session, message);

            Session.RegisterMessage("SSH_MSG_KEX_ECDH_REPLY");

            Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;

            var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];

            basepoint[0] = 9;

            var rnd = new Random();

            _privateKey = new byte[MontgomeryCurve25519.PrivateKeySizeInBytes];
            rnd.NextBytes(_privateKey);

            _clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
            MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0);

            SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));
        }