示例#1
0
        public void TestAgreement()
        {
            using (RandomNumberGenerator random = RandomNumberGenerator.Create())
            {
                byte[] clientPrivateKey = new byte[X25519.KeySize];
                random.GetBytes(clientPrivateKey);

                byte[] clientPublicKey = new byte[X25519.KeySize];
                X25519.Func(clientPublicKey, clientPrivateKey);

                byte[] serverPrivateKey = new byte[X25519.KeySize];
                random.GetBytes(serverPrivateKey);

                byte[] serverPublickey = new byte[X25519.KeySize];
                X25519.Func(serverPublickey, serverPrivateKey);

                // client key aggreement
                byte[] clientSharedSecret = new byte[X25519.KeySize];
                Assert.IsTrue(X25519.Func(clientSharedSecret, clientPrivateKey, serverPublickey));

                // server key agreement
                byte[] serverSharedSecret = new byte[X25519.KeySize];
                Assert.IsTrue(X25519.Func(serverSharedSecret, serverPrivateKey, clientPublicKey));

                CollectionAssert.AreEqual(clientSharedSecret, serverSharedSecret);
            }
        }
        /// <inheritdoc />
        public void EncodeServerKeyExchangeMessage(ByteSpan output, object privateKey)
        {
            RSA rsaPrivateKey = privateKey as RSA;

            if (rsaPrivateKey == null)
            {
                throw new ArgumentException("Invalid private key", nameof(privateKey));
            }

            output[0] = (byte)ECCurveType.NamedCurve;
            output.WriteBigEndian16((ushort)NamedCurve.x25519, 1);
            output[3] = (byte)X25519.KeySize;
            X25519.Func(output.Slice(4, X25519.KeySize), this.privateAgreementKey);

            // Hash the key parameters
            byte[] paramterDigest = this.sha256.ComputeHash(output.GetUnderlyingArray(), output.Offset, 4 + X25519.KeySize);

            // Sign the paramter digest
            RSAPKCS1SignatureFormatter signer = new RSAPKCS1SignatureFormatter(rsaPrivateKey);

            signer.SetHashAlgorithm("SHA256");
            ByteSpan signature = signer.CreateSignature(paramterDigest);

            Debug.Assert(signature.Length == rsaPrivateKey.KeySize / 8);
            output[4 + X25519.KeySize] = (byte)HashAlgorithm.Sha256;
            output[5 + X25519.KeySize] = (byte)SignatureAlgorithm.RSA;
            output.Slice(6 + X25519.KeySize).WriteBigEndian16((ushort)signature.Length);
            signature.CopyTo(output.Slice(8 + X25519.KeySize));
        }
示例#3
0
 public void TestVectors()
 {
     for (int ii = 0, nn = TestVectorData.Length; ii != nn; ++ii)
     {
         byte[] actual = new byte[32];
         bool   result = X25519.Func(actual, TestVectorData[ii].In, TestVectorData[ii].Base);
         Assert.IsTrue(result);
         CollectionAssert.AreEqual(TestVectorData[ii].Expect, actual, $"Test vector {ii} mismatch");
     }
 }
        /// <inheritdoc />
        public bool VerifyClientMessageAndGenerateSharedKey(ByteSpan output, ByteSpan clientKeyExchangeMessage)
        {
            if (clientKeyExchangeMessage.Length != ClientMessageSize)
            {
                return(false);
            }
            else if (clientKeyExchangeMessage[0] != (byte)X25519.KeySize)
            {
                return(false);
            }

            ByteSpan othersPublicKey = clientKeyExchangeMessage.Slice(1);

            return(X25519.Func(output, this.privateAgreementKey, othersPublicKey));
        }
示例#5
0
        public void TestLowOrderPoints()
        {
            using (RandomNumberGenerator random = RandomNumberGenerator.Create())
            {
                byte[] scalar = new byte[X25519.KeySize];
                random.GetBytes(scalar);

                for (int ii = 0, nn = LowOrderPoints.Length; ii != nn; ++ii)
                {
                    ByteSpan output = new byte[X25519.KeySize];
                    bool     result = X25519.Func(output, scalar, LowOrderPoints[ii]);
                    Assert.IsFalse(result, $"Multiplication by low order point {ii} succeeded: should have failed");
                }
            }
        }
 /// <inheritdoc />
 public void EncodeClientKeyExchangeMessage(ByteSpan output)
 {
     output[0] = (byte)X25519.KeySize;
     X25519.Func(output.Slice(1, X25519.KeySize), this.privateAgreementKey);
 }
        /// <inheritdoc />
        public bool VerifyServerMessageAndGenerateSharedKey(ByteSpan output, ByteSpan serverKeyExchangeMessage, object publicKey)
        {
            RSA rsaPublicKey = publicKey as RSA;

            if (rsaPublicKey == null)
            {
                return(false);
            }
            else if (output.Length != X25519.KeySize)
            {
                return(false);
            }

            // Verify message is compatible with this cipher suite
            if (serverKeyExchangeMessage.Length != CalculateServerMessageSize(rsaPublicKey.KeySize))
            {
                return(false);
            }
            else if (serverKeyExchangeMessage[0] != (byte)ECCurveType.NamedCurve)
            {
                return(false);
            }
            else if (serverKeyExchangeMessage.ReadBigEndian16(1) != (ushort)NamedCurve.x25519)
            {
                return(false);
            }
            else if (serverKeyExchangeMessage[3] != X25519.KeySize)
            {
                return(false);
            }
            else if (serverKeyExchangeMessage[4 + X25519.KeySize] != (byte)HashAlgorithm.Sha256)
            {
                return(false);
            }
            else if (serverKeyExchangeMessage[5 + X25519.KeySize] != (byte)SignatureAlgorithm.RSA)
            {
                return(false);
            }

            ByteSpan keyParameters   = serverKeyExchangeMessage.Slice(0, 4 + X25519.KeySize);
            ByteSpan othersPublicKey = keyParameters.Slice(4);
            ushort   signatureSize   = serverKeyExchangeMessage.ReadBigEndian16(6 + X25519.KeySize);
            ByteSpan signature       = serverKeyExchangeMessage.Slice(4 + keyParameters.Length);

            if (signatureSize != signature.Length)
            {
                return(false);
            }

            // Hash the key parameters
            byte[] parameterDigest = this.sha256.ComputeHash(keyParameters.GetUnderlyingArray(), keyParameters.Offset, keyParameters.Length);

            // Verify the signature
            RSAPKCS1SignatureDeformatter verifier = new RSAPKCS1SignatureDeformatter(rsaPublicKey);

            verifier.SetHashAlgorithm("SHA256");
            if (!verifier.VerifySignature(parameterDigest, signature.ToArray()))
            {
                return(false);
            }

            // Signature has been validated, generate the shared key
            return(X25519.Func(output, this.privateAgreementKey, othersPublicKey));
        }