protected override void ProcessCertificateVerify(HandshakeMessage verify) { if (_state != HandshakeState.ReceivedClientKeyExchange) { throw new AlertException(AlertDescription.UnexpectedMessage, "Certificate verify received at the wrong time"); } if (!_clientCertificateReceived) { throw new AlertException(AlertDescription.UnexpectedMessage, "Certificate verify received even though client certificate not received"); } // Get all handshake messages up to, but not including, this one byte[] allMessages = _handshakeStream.ToArray(); byte[] handshakeMessages = new byte[allMessages.Length - verify.Encode().Length]; Buffer.BlockCopy(allMessages, 0, handshakeMessages, 0, handshakeMessages.Length); // Verify the signature of handshake messages CertificatePublicKey publicKey = new CertificatePublicKey(_clientCertificates[0]); bool signatureOk = VerifySignature(publicKey, handshakeMessages, verify.Data); if (!signatureOk) { throw new AlertException(AlertDescription.DecodeError, "Signature from client incorrect"); } // Wait for changecipherspec+finished _state = HandshakeState.ReceivedClientKeyExchange; }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { if (!(publicKey.Algorithm is RSACryptoServiceProvider)) { throw new CryptographicException("RSA key exchange requires RSA public key"); } return GetClientKeys(version, clientVersion, (RSACryptoServiceProvider)publicKey.Algorithm); }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey key, byte[] signature) { if (signature.Length == 0) { return true; } return false; }
protected bool VerifySignature(CertificatePublicKey publicKey, byte[] data, byte[] signedParams) { // Initialize the signature position and validity int position = 0; bool signatureOk = false; // Get the corresponding signer for public key SignatureAlgorithm sigAlg = _pluginManager.GetSignatureAlgorithmByOid(publicKey.Oid); if (sigAlg == null) { throw new AlertException(AlertDescription.IllegalParameter, "Signer for given public key not found"); } // Select hash algorithm, null means SSLv3/TLSv1 hash HashAlgorithm hashAlgorithm = null; if (_version.HasSelectableSighash) { byte hashAlgorithmType = signedParams[position++]; byte signAlgorithmType = signedParams[position++]; if (sigAlg.SignatureAlgorithmType != signAlgorithmType) { throw new AlertException(AlertDescription.DecryptError, "Certificate signed with invalid signature algorithm"); } if (!sigAlg.SupportsHashAlgorithmType(hashAlgorithmType)) { throw new AlertException(AlertDescription.DecryptError, "Certificate signed with invalid hash algorithm"); } hashAlgorithm = GetSignatureHashAlgorithm(sigAlg, hashAlgorithmType); } // Check that signature length is valid (same as stored) int len = (signedParams[position] << 8) | signedParams[position + 1]; if (len != signedParams.Length - position - 2) { throw new AlertException(AlertDescription.DecodeError, "Signature length not valid"); } position += 2; // Extract the signature from the end of the signed parameters byte[] signature = new byte[len]; Buffer.BlockCopy(signedParams, position, signature, 0, len); // Verify correctness of the signature signatureOk = sigAlg.VerifyData(_version, data, hashAlgorithm, publicKey, signature); if (!signatureOk) { throw new AlertException(AlertDescription.DecodeError, "Signature from server incorrect"); } return(signatureOk); }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { byte[] ecPoint = Blob2Point(_ecdhCng.PublicKey.ToByteArray()); byte[] ret = new byte[1+ecPoint.Length]; ret[0] = (byte) (ecPoint.Length); Buffer.BlockCopy(ecPoint, 0, ret, 1, ecPoint.Length); return ret; }
public override bool VerifyData(byte[] buffer, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (!CertificateKeyAlgorithm.Equals(publicKey.Oid)) { throw new Exception("ECDSA signature verification requires ECDSA public key"); } string curveOid = DER2OID(publicKey.Parameters); if (curveOid == null) { throw new Exception("Unsupported ECDSA public key parameters"); } byte[] keyData = publicKey.KeyValue; if (keyData[0] != 0x04) { throw new Exception("Only uncompressed ECDSA keys supported, format: " + keyData[0]); } UInt32 keyLength; byte[] blobMagic; if (curveOid.Equals(P256OID)) { keyLength = 32; blobMagic = Encoding.ASCII.GetBytes("ECS1"); } else if (curveOid.Equals(P384OID)) { keyLength = 48; blobMagic = Encoding.ASCII.GetBytes("ECS3"); } else if (curveOid.Equals(P521OID)) { keyLength = 66; blobMagic = Encoding.ASCII.GetBytes("ECS5"); } else { throw new Exception("Unsupported ECC curve type OID: " + curveOid); } if (2*keyLength != keyData.Length-1) { throw new Exception("Invalid length of ECDSA public key: " + keyData.Length + " (should be " + (1+2*keyLength) + ")"); } byte[] lengthData = BitConverter.GetBytes(keyLength); // Create the ECC public blob for ECDsaCng class byte[] eccBlob = new byte[8+2*keyLength]; Buffer.BlockCopy(blobMagic, 0, eccBlob, 0, 4); Buffer.BlockCopy(lengthData, 0, eccBlob, 4, 4); Buffer.BlockCopy(keyData, 1, eccBlob, 8, (int) (2*keyLength)); CngKey cngKey = CngKey.Import(eccBlob, CngKeyBlobFormat.EccPublicBlob); ECDsaCng ecdsaKey = new ECDsaCng(cngKey); ecdsaKey.HashAlgorithm = GetCngAlgorithm(hashAlgorithm); return ecdsaKey.VerifyData(buffer, DERDecodeSignature(signature, (int)keyLength)); }
protected override void ProcessServerKeyExchange(HandshakeMessage keyExchange) { if (_state != HandshakeState.ReceivedServerHello && _state != HandshakeState.ReceivedCertificate) { throw new AlertException(AlertDescription.UnexpectedMessage, "Server key exchange received at the wrong time"); } if (!_cipherSuite.IsAnonymous && _serverCertificates.Count == 0) { throw new AlertException(AlertDescription.HandshakeFailure, "No certificate received even though cipher suite is not anonymous"); } // Process server keys, also returns us the signature data var cert = _serverCertificates[0]; byte[] signature = _cipherSuite.KeyExchangeAlgorithm.ProcessServerKeys(_version, keyExchange.Data, cert); // Extract the signed data from the complete payload byte[] serverKeys = new byte[keyExchange.Data.Length - signature.Length]; Buffer.BlockCopy(keyExchange.Data, 0, serverKeys, 0, serverKeys.Length); // Verify correctness of the signature if (!_cipherSuite.IsAnonymous) { CertificatePublicKey publicKey = new CertificatePublicKey(cert); // Generate the original data signed from server keys byte[] signedData = new byte[_connectionState.ClientRandom.Length + _connectionState.ServerRandom.Length + serverKeys.Length]; Buffer.BlockCopy(_connectionState.ClientRandom, 0, signedData, 0, _connectionState.ClientRandom.Length); Buffer.BlockCopy(_connectionState.ServerRandom, 0, signedData, _connectionState.ClientRandom.Length, _connectionState.ServerRandom.Length); Buffer.BlockCopy(serverKeys, 0, signedData, _connectionState.ClientRandom.Length + _connectionState.ServerRandom.Length, serverKeys.Length); bool signatureOk = VerifySignature(publicKey, signedData, signature); if (!signatureOk) { throw new AlertException(AlertDescription.DecodeError, "Signature from server incorrect"); } } // Wait for certificate request or server hello done _state = HandshakeState.ReceivedServerKeyExchange; }
public static void Load() { string path = System.Reflection.Assembly.GetExecutingAssembly().Location; string directory = Path.GetDirectoryName(path); CipherSuitePluginManager pluginManager = new CipherSuitePluginManager(directory); X509Certificate2 cert = new X509Certificate2(Convert.FromBase64String(Pfx), "temp", X509KeyStorageFlags.Exportable); PublicKey = new CertificatePublicKey(cert); PrivateKey = new CertificatePrivateKey("1.2.840.113549.1.1.1", cert.PrivateKey); SecurityParameters = new SecurityParameters() { MaximumVersion = ProtocolVersion.TLS1_0 }; SecurityParameters.CipherSuiteIDs.Add(0x0039); // TLS_DHE_RSA_WITH_AES_256_CBC_SHA SecurityParameters.AddCertificate(new X509CertificateCollection(new X509Certificate[] { cert }), PrivateKey); Certificate = cert; }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { return null; }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { byte[] ecPoint = Blob2Point(_ecdhCng.PublicKey.ToByteArray()); byte[] ret = new byte[1 + ecPoint.Length]; ret[0] = (byte)(ecPoint.Length); Buffer.BlockCopy(ecPoint, 0, ret, 1, ecPoint.Length); return(ret); }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { if (!(publicKey.Algorithm is RSACryptoServiceProvider)) { throw new CryptographicException("RSA key exchange requires RSA public key"); } return(GetClientKeys(version, clientVersion, (RSACryptoServiceProvider)publicKey.Algorithm)); }
public override bool VerifyData(byte[] buffer, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (!CertificateKeyAlgorithm.Equals(publicKey.Oid)) { throw new Exception("ECDSA signature verification requires ECDSA public key"); } string curveOid = DER2OID(publicKey.Parameters); if (curveOid == null) { throw new Exception("Unsupported ECDSA public key parameters"); } byte[] keyData = publicKey.KeyValue; if (keyData[0] != 0x04) { throw new Exception("Only uncompressed ECDSA keys supported, format: " + keyData[0]); } UInt32 keyLength; byte[] blobMagic; if (curveOid.Equals(P256OID)) { keyLength = 32; blobMagic = Encoding.ASCII.GetBytes("ECS1"); } else if (curveOid.Equals(P384OID)) { keyLength = 48; blobMagic = Encoding.ASCII.GetBytes("ECS3"); } else if (curveOid.Equals(P521OID)) { keyLength = 66; blobMagic = Encoding.ASCII.GetBytes("ECS5"); } else { throw new Exception("Unsupported ECC curve type OID: " + curveOid); } if (2 * keyLength != keyData.Length - 1) { throw new Exception("Invalid length of ECDSA public key: " + keyData.Length + " (should be " + (1 + 2 * keyLength) + ")"); } byte[] lengthData = BitConverter.GetBytes(keyLength); // Create the ECC public blob for ECDsaCng class byte[] eccBlob = new byte[8 + 2 * keyLength]; Buffer.BlockCopy(blobMagic, 0, eccBlob, 0, 4); Buffer.BlockCopy(lengthData, 0, eccBlob, 4, 4); Buffer.BlockCopy(keyData, 1, eccBlob, 8, (int)(2 * keyLength)); CngKey cngKey = CngKey.Import(eccBlob, CngKeyBlobFormat.EccPublicBlob); ECDsaCng ecdsaKey = new ECDsaCng(cngKey); ecdsaKey.HashAlgorithm = GetCngAlgorithm(hashAlgorithm); return(ecdsaKey.VerifyData(buffer, DERDecodeSignature(signature, (int)keyLength))); }
// Returns the client key exchange message as a byte array public abstract byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey);
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (!CertificateKeyAlgorithm.Equals(publicKey.Oid)) { throw new Exception("ECDSA signature verification requires ECDSA public key"); } // Decode the public key parameters string curveOid = DER2OID(publicKey.Parameters); if (curveOid == null) { throw new Exception("Unsupported ECDSA public key parameters"); } // Get parameters from the curve OID X9ECParameters ecParams = SecNamedCurves.GetByOid(new DerObjectIdentifier(curveOid)); if (ecParams == null) { throw new Exception("Unsupported ECC curve type OID: " + curveOid); } // Construct domain parameters ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed()); // Decode the public key data byte[] ecPointData = publicKey.KeyValue; if (ecPointData[0] != 0x04) { throw new Exception("Only uncompressed ECDSA keys supported, format: " + ecPointData[0]); } ECPoint ecPoint = domainParameters.Curve.DecodePoint(ecPointData); ECPublicKeyParameters theirPublicKey = new ECPublicKeyParameters(ecPoint, domainParameters); // Hash input data buffer byte[] dataHash; if (hashAlgorithm == null) { dataHash = TLSv1HashData(data); } else { dataHash = hashAlgorithm.ComputeHash(data); } // Actually verify the signature BigInteger[] sig = DERDecodeSignature(signature); var r = sig[0]; var s = sig[1]; Log.Trace("Hashed data (V): " + BitConverter.ToString(dataHash)); Log.Trace("Public Key Q (V): " + BitConverter.ToString(theirPublicKey.Q.GetEncoded())); Log.Trace("Signature R (V): " + BitConverter.ToString(r.ToByteArrayUnsigned())); Log.Trace("Signature S (V): " + BitConverter.ToString(s.ToByteArrayUnsigned())); Log.Trace("R value: " + sig[0].SignValue + " " + sig[0].LongValue); Log.Trace("S value: " + sig[1].SignValue + " " + sig[1].LongValue); ECDsaSigner signer = new ECDsaSigner(); signer.Init(false, theirPublicKey); var result = signer.VerifySignature(dataHash, r, s); Log.Debug("Signature verification status: {0}.", result); return result; }
protected override void ProcessServerHelloDone(HandshakeMessage serverHelloDone) { if (_state != HandshakeState.ReceivedCertificate && _state != HandshakeState.ReceivedServerKeyExchange && _state != HandshakeState.ReceivedCertificateRequest) { throw new AlertException(AlertDescription.UnexpectedMessage, "Server hello done received at the wrong time"); } bool clientCertificateSent = false; if (_clientCertificateRequested) { // Ask for correct certificate from the callback int certificateIndex = _certificateSelectionCallback(_availableCertificates.ToArray(), _serverCertificates); if (certificateIndex >= 0 && certificateIndex < _availableCertificates.Count) { _clientCertificates.AddRange(_availableCertificates[certificateIndex]); _selectedPrivateKey = _availablePrivateKeys[certificateIndex]; } // If certificate was selected, send it to server if (_clientCertificates.Count > 0) { HandshakeCertificate certificate = new HandshakeCertificate(_version); certificate.CertificateList.AddRange(_clientCertificates); OutputMessage(certificate); clientCertificateSent = true; } else { // TODO: In case of SSLv3 we should send warning alert instead? HandshakeCertificate certificate = new HandshakeCertificate(_version); OutputMessage(certificate); } } // Send client key exchange message byte[] clientKeys = null; if (_serverCertificates.Count > 0) { CertificatePublicKey publicKey = new CertificatePublicKey(_serverCertificates[0]); clientKeys = _cipherSuite.KeyExchangeAlgorithm.GetClientKeys(_version, _maxVersion, publicKey); } HandshakeMessage keyex = new HandshakeMessage(HandshakeMessageType.ClientKeyExchange, _version, clientKeys); OutputMessage(keyex); if (clientCertificateSent) { // Get all handshake messages byte[] handshakeMessages = _handshakeStream.ToArray(); // FIXME: Generate the signature of handshakeMessages with client cert signature // this breaks if client certificate signature is different type than negotiated byte[] signature = GenerateSignature(_selectedPrivateKey, handshakeMessages); // Create CertificateVerify message and send it to server HandshakeMessage verify = new HandshakeMessage(HandshakeMessageType.CertificateVerify, _version, signature); OutputMessage(verify); } // Generate the master secret from key exchange _connectionState.MasterSecret = GenerateMasterSecret(_version, _cipherSuite, _connectionState); // Wait for changecipherspec+finished _state = HandshakeState.SendChangeCipherSpec; }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { byte[] ecPoint = this.publicKey.Q.GetEncoded(); byte[] ret = new byte[1 + ecPoint.Length]; ret[0] = (byte)ecPoint.Length; Buffer.BlockCopy(ecPoint, 0, ret, 1, ecPoint.Length); return ret; }
protected override void ProcessServerHelloDone(HandshakeMessage serverHelloDone) { if (_state != HandshakeState.ReceivedCertificate && _state != HandshakeState.ReceivedServerKeyExchange && _state != HandshakeState.ReceivedCertificateRequest) { throw new AlertException(AlertDescription.UnexpectedMessage, "Server hello done received at the wrong time"); } bool clientCertificateSent = false; if (_clientCertificateRequested) { // Ask for correct certificate from the callback int certificateIndex = _certificateSelectionCallback(_availableCertificates.ToArray(), _serverCertificates); if (certificateIndex >= 0 && certificateIndex < _availableCertificates.Count) { _clientCertificates.AddRange(_availableCertificates[certificateIndex]); _selectedPrivateKey = _availablePrivateKeys[certificateIndex]; } // If certificate was selected, send it to server if (_clientCertificates.Count > 0) { HandshakeCertificate certificate = new HandshakeCertificate(_version); certificate.CertificateList.AddRange(_clientCertificates); OutputMessage(certificate); clientCertificateSent = true; } else { // TODO: In case of SSLv3 we should send warning alert instead? HandshakeCertificate certificate = new HandshakeCertificate(_version); OutputMessage(certificate); } } // Send client key exchange message byte[] clientKeys = null; if (_serverCertificates.Count > 0) { var cert = _serverCertificates[0]; CertificatePublicKey publicKey = new CertificatePublicKey(cert); this.logger?.Trace($"OID (lookup with http://www.oid-info.com/get/[oid]) of key from server certificate: {publicKey.Oid}"); var data = Asn1Object.FromByteArray(cert.GetKeyAlgorithmParameters()); this.logger?.Trace($" OID of key parameters from server certificate: {data}"); clientKeys = _cipherSuite.KeyExchangeAlgorithm.GetClientKeys(_version, _maxVersion, publicKey); } HandshakeMessage keyex = new HandshakeMessage(HandshakeMessageType.ClientKeyExchange, _version, clientKeys); OutputMessage(keyex); if (clientCertificateSent) { // Get all handshake messages byte[] handshakeMessages = _handshakeStream.ToArray(); // FIXME: Generate the signature of handshakeMessages with client cert signature // this breaks if client certificate signature is different type than negotiated byte[] signature = GenerateSignature(_selectedPrivateKey, handshakeMessages); // Create CertificateVerify message and send it to server HandshakeMessage verify = new HandshakeMessage(HandshakeMessageType.CertificateVerify, _version, signature); OutputMessage(verify); } // Generate the master secret from key exchange _connectionState.MasterSecret = GenerateMasterSecret(_version, _cipherSuite, _connectionState); // Wait for changecipherspec+finished _state = HandshakeState.SendChangeCipherSpec; }
public abstract bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature);
public bool ReadPacket(Stream stream) { byte[] header = new byte[5]; int readBytes = 0; while (readBytes < header.Length) { readBytes += stream.Read(header, readBytes, header.Length - readBytes); } Record record = new Record(header); readBytes = 0; while (readBytes < record.Fragment.Length) { readBytes += stream.Read(record.Fragment, readBytes, record.Fragment.Length - readBytes); } _recordHandler.ProcessInputRecord(record); if (record.Type == 22) { HandshakeMessage hs = HandshakeMessage.GetInstance(VERSION, record.Fragment); if (hs == null) { Console.WriteLine("Skipped handling packet"); return(true); } Console.WriteLine("adding bytes to hash " + record.Fragment.Length); _handshakeStream.Write(record.Fragment, 0, record.Fragment.Length); if (hs.Type == HandshakeMessageType.ServerHello) { HandshakeServerHello sh = (HandshakeServerHello)hs; _serverRandom = sh.Random.GetBytes(); if (sh.ServerVersion != VERSION) { throw new Exception("Version doesn't match"); } } else if (hs.Type == HandshakeMessageType.Certificate) { Console.WriteLine("Found certificate"); HandshakeCertificate cert = (HandshakeCertificate)hs; _rsaPublicKey = null; foreach (X509Certificate c in cert.CertificateList) { Console.WriteLine(c.ToString(true)); if (_rsaPublicKey == null) { X509Certificate c2 = new X509Certificate(c); _rsaPublicKey = new CertificatePublicKey(c2); } } } else if (hs.Type == HandshakeMessageType.ServerHelloDone) { SendClientKey(stream); byte[] seed = new byte[64]; Array.Copy(_clientRandom, 0, seed, 0, 32); Array.Copy(_serverRandom, 0, seed, 32, 32); PrintBytes("hash seed", seed); _masterSecret = _cipherSuite.KeyExchangeAlgorithm.GetMasterSecret(_cipherSuite.PseudoRandomFunction, seed); PrintBytes("master secret", _masterSecret); seed = new byte[64]; Array.Copy(_serverRandom, 0, seed, 0, 32); Array.Copy(_clientRandom, 0, seed, 32, 32); ConnectionState connectionState = new ConnectionState(_clientRandom, _serverRandom, _masterSecret); _recordHandler.SetCipherSuite(_cipherSuite, connectionState); SendFinished(stream); } else if (hs.Type == HandshakeMessageType.Finished) { Console.WriteLine("Got Finished message!!!"); SendHttpGet(stream); } } else if (record.Type == 20) { Console.WriteLine("Got change cipher spec from server"); _recordHandler.ChangeRemoteState(); } else if (record.Type == 21) { // This is an alert if (record.Fragment.Length >= 2 && record.Fragment[1] == 0) { // Close notify Console.WriteLine("Close notify received"); return(false); } } else if (record.Type == 23) { Console.WriteLine("Got data: " + Encoding.UTF8.GetString(record.Fragment)); } return(true); }
protected override void ProcessServerKeyExchange(HandshakeMessage keyExchange) { if (_state != HandshakeState.ReceivedServerHello && _state != HandshakeState.ReceivedCertificate) { throw new AlertException(AlertDescription.UnexpectedMessage, "Server key exchange received at the wrong time"); } if (!_cipherSuite.IsAnonymous && _serverCertificates.Count == 0) { throw new AlertException(AlertDescription.HandshakeFailure, "No certificate received even though cipher suite is not anonymous"); } // Process server keys, also returns us the signature data byte[] signature = _cipherSuite.KeyExchangeAlgorithm.ProcessServerKeys(_version, keyExchange.Data); // Extract the signed data from the complete payload byte[] serverKeys = new byte[keyExchange.Data.Length - signature.Length]; Buffer.BlockCopy(keyExchange.Data, 0, serverKeys, 0, serverKeys.Length); // Verify correctness of the signature if (!_cipherSuite.IsAnonymous) { CertificatePublicKey publicKey = new CertificatePublicKey(_serverCertificates[0]); // Generate the original data signed from server keys byte[] signedData = new byte[_connectionState.ClientRandom.Length + _connectionState.ServerRandom.Length + serverKeys.Length]; Buffer.BlockCopy(_connectionState.ClientRandom, 0, signedData, 0, _connectionState.ClientRandom.Length); Buffer.BlockCopy(_connectionState.ServerRandom, 0, signedData, _connectionState.ClientRandom.Length, _connectionState.ServerRandom.Length); Buffer.BlockCopy(serverKeys, 0, signedData, _connectionState.ClientRandom.Length + _connectionState.ServerRandom.Length, serverKeys.Length); bool signatureOk = VerifySignature(publicKey, signedData, signature); if (!signatureOk) { throw new AlertException(AlertDescription.DecodeError, "Signature from server incorrect"); } } // Wait for certificate request or server hello done _state = HandshakeState.ReceivedServerKeyExchange; }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (!CertificateKeyAlgorithm.Equals(publicKey.Oid)) { throw new Exception("RSA signature verification requires RSA public key"); } RSACryptoServiceProvider rsaKey = (RSACryptoServiceProvider)publicKey.Algorithm; if (hashAlgorithm == null) { // Before TLS 1.2 RSA signatures always used MD5+SHA1 // MD5+SHA1 is not supported by .NET, so we need custom code return(TLSv1VerifyData(rsaKey, data, signature)); } else { // Starting from TLS 1.2 the standard signature is used return(rsaKey.VerifyData(data, hashAlgorithm, signature)); } }
protected bool VerifySignature(CertificatePublicKey publicKey, byte[] data, byte[] signedParams) { // Initialize the signature position and validity int position = 0; bool signatureOk = false; // Get the corresponding signer for public key SignatureAlgorithm sigAlg = _pluginManager.GetSignatureAlgorithmByOid(publicKey.Oid); if (sigAlg == null) { throw new AlertException(AlertDescription.IllegalParameter, "Signer for given public key not found"); } // Select hash algorithm, null means SSLv3/TLSv1 hash HashAlgorithm hashAlgorithm = null; if (_version.HasSelectableSighash) { byte hashAlgorithmType = signedParams[position++]; byte signAlgorithmType = signedParams[position++]; if (sigAlg.SignatureAlgorithmType != signAlgorithmType) { throw new AlertException(AlertDescription.DecryptError, "Certificate signed with invalid signature algorithm"); } if (!sigAlg.SupportsHashAlgorithmType(hashAlgorithmType)) { throw new AlertException(AlertDescription.DecryptError, "Certificate signed with invalid hash algorithm"); } hashAlgorithm = GetSignatureHashAlgorithm(sigAlg, hashAlgorithmType); } // Check that signature length is valid (same as stored) int len = (signedParams[position] << 8) | signedParams[position+1]; if (len != signedParams.Length-position-2) { throw new AlertException(AlertDescription.DecodeError, "Signature length not valid"); } position += 2; // Extract the signature from the end of the signed parameters byte[] signature = new byte[len]; Buffer.BlockCopy(signedParams, position, signature, 0, len); // Verify correctness of the signature signatureOk = sigAlg.VerifyData(_version, data, hashAlgorithm, publicKey, signature); if (!signatureOk) { throw new AlertException(AlertDescription.DecodeError, "Signature from server incorrect"); } return signatureOk; }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { byte[] ecPoint = this.publicKey.Q.GetEncoded(); byte[] ret = new byte[1 + ecPoint.Length]; ret[0] = (byte)ecPoint.Length; Buffer.BlockCopy(ecPoint, 0, ret, 1, ecPoint.Length); return(ret); }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (hashAlgorithm != null && !(hashAlgorithm is SHA1)) { throw new Exception("DSA signature verification requires SHA1 hash algorithm"); } if (!CertificateKeyAlgorithm.Equals(publicKey.Oid) || !(publicKey.Algorithm is DSACryptoServiceProvider)) { throw new Exception("DSA signature verification requires DSA public key"); } return VerifyData(data, (DSACryptoServiceProvider)publicKey.Algorithm, signature); }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (!CertificateKeyAlgorithm.Equals(publicKey.Oid)) { throw new Exception("ECDSA signature verification requires ECDSA public key"); } // Decode the public key parameters string curveOid = DER2OID(publicKey.Parameters); if (curveOid == null) { throw new Exception("Unsupported ECDSA public key parameters"); } // Get parameters from the curve OID X9ECParameters ecParams = SecNamedCurves.GetByOid(new DerObjectIdentifier(curveOid)); if (ecParams == null) { throw new Exception("Unsupported ECC curve type OID: " + curveOid); } // Construct domain parameters ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed()); // Decode the public key data byte[] ecPointData = publicKey.KeyValue; if (ecPointData[0] != 0x04) { throw new Exception("Only uncompressed ECDSA keys supported, format: " + ecPointData[0]); } ECPoint ecPoint = domainParameters.Curve.DecodePoint(ecPointData); ECPublicKeyParameters theirPublicKey = new ECPublicKeyParameters(ecPoint, domainParameters); // Hash input data buffer byte[] dataHash; if (hashAlgorithm == null) { dataHash = TLSv1HashData(data); } else { dataHash = hashAlgorithm.ComputeHash(data); } // Actually verify the signature BigInteger[] sig = DERDecodeSignature(signature); ECDsaSigner signer = new ECDsaSigner(); signer.Init(false, theirPublicKey); return(signer.VerifySignature(dataHash, sig[0], sig[1])); }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { if (_dh_p.Length == 0 || _dh_g.Length == 0 || _dh_Ys.Length == 0) throw new Exception("Server keys not generated/received"); // Create corresponding BigIntegers BigInteger p = ByteArrayToBigInteger(_dh_p); BigInteger g = ByteArrayToBigInteger(_dh_g); BigInteger Ys = ByteArrayToBigInteger(_dh_Ys); // Generate new private value X between 0 and P-1 BigInteger x = GenerateX(p); // Calculate pre-master secret BigInteger Z = BigInteger.ModPow(Ys, x, p); _preMasterSecret = BigIntegerToByteArray(Z, _pLength); // Calculate the client parameter BigInteger Yc = BigInteger.ModPow(g, x, p); _dh_Yc = BigIntegerToByteArray(Yc, _pLength); // Return the client parameter that will be sent byte[] ret = new byte[2+_dh_Yc.Length]; ret[0] = (byte) (_dh_Yc.Length >> 8); ret[1] = (byte) (_dh_Yc.Length); Buffer.BlockCopy(_dh_Yc, 0, ret, 2, _dh_Yc.Length); return ret; }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (!CertificateKeyAlgorithm.Equals(publicKey.Oid)) { throw new Exception("ECDSA signature verification requires ECDSA public key"); } // Decode the public key parameters string curveOid = DER2OID(publicKey.Parameters); if (curveOid == null) { throw new Exception("Unsupported ECDSA public key parameters"); } // Get parameters from the curve OID X9ECParameters ecParams = SecNamedCurves.GetByOid(new DerObjectIdentifier(curveOid)); if (ecParams == null) { throw new Exception("Unsupported ECC curve type OID: " + curveOid); } // Construct domain parameters ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed()); // Decode the public key data byte[] ecPointData = publicKey.KeyValue; if (ecPointData[0] != 0x04) { throw new Exception("Only uncompressed ECDSA keys supported, format: " + ecPointData[0]); } Org.BouncyCastle.Math.EC.ECPoint ecPoint = domainParameters.Curve.DecodePoint(ecPointData); ECPublicKeyParameters theirPublicKey = new ECPublicKeyParameters(ecPoint, domainParameters); // Hash input data buffer byte[] dataHash; if (hashAlgorithm == null) { dataHash = TLSv1HashData(data); } else { dataHash = hashAlgorithm.ComputeHash(data); } // Actually verify the signature BigInteger[] sig = DERDecodeSignature(signature); var r = sig[0]; var s = sig[1]; Log.Trace("Hashed data (V): " + BitConverter.ToString(dataHash)); Log.Trace("Public Key Q (V): " + BitConverter.ToString(theirPublicKey.Q.GetEncoded())); Log.Trace("Signature R (V): " + BitConverter.ToString(r.ToByteArrayUnsigned())); Log.Trace("Signature S (V): " + BitConverter.ToString(s.ToByteArrayUnsigned())); Log.Trace("R value: " + sig[0].SignValue + " " + sig[0].LongValue); Log.Trace("S value: " + sig[1].SignValue + " " + sig[1].LongValue); ECDsaSigner signer = new ECDsaSigner(); signer.Init(false, theirPublicKey); var result = signer.VerifySignature(dataHash, r, s); Log.Debug("Signature verification status: {0}.", result); return(result); }
public bool ReadPacket(Stream stream) { byte[] header = new byte[5]; int readBytes = 0; while (readBytes < header.Length) { readBytes += stream.Read(header, readBytes, header.Length-readBytes); } Record record = new Record(header); readBytes = 0; while (readBytes < record.Fragment.Length) { readBytes += stream.Read(record.Fragment, readBytes, record.Fragment.Length-readBytes); } _recordHandler.ProcessInputRecord(record); if (record.Type == 22) { HandshakeMessage hs = HandshakeMessage.GetInstance(VERSION, record.Fragment); if (hs == null) { Console.WriteLine("Skipped handling packet"); return true; } Console.WriteLine("adding bytes to hash " + record.Fragment.Length); _handshakeStream.Write(record.Fragment, 0, record.Fragment.Length); if (hs.Type == HandshakeMessageType.ServerHello) { HandshakeServerHello sh = (HandshakeServerHello) hs; _serverRandom = sh.Random.GetBytes(); if (sh.ServerVersion != VERSION) { throw new Exception("Version doesn't match"); } } else if (hs.Type == HandshakeMessageType.Certificate) { Console.WriteLine("Found certificate"); HandshakeCertificate cert = (HandshakeCertificate) hs; _rsaPublicKey = null; foreach (X509Certificate c in cert.CertificateList) { Console.WriteLine(c.ToString(true)); if (_rsaPublicKey == null) { X509Certificate c2 = new X509Certificate(c); _rsaPublicKey = new CertificatePublicKey(c2); } } } else if (hs.Type == HandshakeMessageType.ServerHelloDone) { SendClientKey(stream); byte[] seed = new byte[64]; Array.Copy(_clientRandom, 0, seed, 0, 32); Array.Copy(_serverRandom, 0, seed, 32, 32); PrintBytes("hash seed", seed); _masterSecret = _cipherSuite.KeyExchangeAlgorithm.GetMasterSecret(_cipherSuite.PseudoRandomFunction, seed); PrintBytes("master secret", _masterSecret); seed = new byte[64]; Array.Copy(_serverRandom, 0, seed, 0, 32); Array.Copy(_clientRandom, 0, seed, 32, 32); ConnectionState connectionState = new ConnectionState(_clientRandom, _serverRandom, _masterSecret); _recordHandler.SetCipherSuite(_cipherSuite, connectionState); SendFinished(stream); } else if (hs.Type == HandshakeMessageType.Finished) { Console.WriteLine("Got Finished message!!!"); SendHttpGet(stream); } } else if (record.Type == 20) { Console.WriteLine("Got change cipher spec from server"); _recordHandler.ChangeRemoteState(); } else if (record.Type == 21) { // This is an alert if (record.Fragment.Length >= 2 && record.Fragment[1] == 0) { // Close notify Console.WriteLine("Close notify received"); return false; } } else if (record.Type == 23) { Console.WriteLine("Got data: " + Encoding.UTF8.GetString(record.Fragment)); } return true; }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (hashAlgorithm != null && !(hashAlgorithm is SHA1)) { throw new Exception("DSA signature verification requires SHA1 hash algorithm"); } if (!CertificateKeyAlgorithm.Equals(publicKey.Oid) || !(publicKey.Algorithm is DSACryptoServiceProvider)) { throw new Exception("DSA signature verification requires DSA public key"); } return(VerifyData(data, (DSACryptoServiceProvider)publicKey.Algorithm, signature)); }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { if (_dh_p.Length == 0 || _dh_g.Length == 0 || _dh_Ys.Length == 0) { throw new Exception("Server keys not generated/received"); } // Create corresponding BigIntegers BigInteger p = ByteArrayToBigInteger(_dh_p); BigInteger g = ByteArrayToBigInteger(_dh_g); BigInteger Ys = ByteArrayToBigInteger(_dh_Ys); // Generate new private value X between 0 and P-1 BigInteger x = GenerateX(p); // Calculate pre-master secret BigInteger Z = BigInteger.ModPow(Ys, x, p); _preMasterSecret = BigIntegerToByteArray(Z, _pLength); // Calculate the client parameter BigInteger Yc = BigInteger.ModPow(g, x, p); _dh_Yc = BigIntegerToByteArray(Yc, _pLength); // Return the client parameter that will be sent byte[] ret = new byte[2 + _dh_Yc.Length]; ret[0] = (byte)(_dh_Yc.Length >> 8); ret[1] = (byte)(_dh_Yc.Length); Buffer.BlockCopy(_dh_Yc, 0, ret, 2, _dh_Yc.Length); return(ret); }
public override byte[] GetClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePublicKey publicKey) { return(null); }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey key, byte[] signature) { if (signature.Length == 0) { return(true); } return(false); }
public override bool VerifyData(ProtocolVersion version, byte[] data, HashAlgorithm hashAlgorithm, CertificatePublicKey publicKey, byte[] signature) { if (!CertificateKeyAlgorithm.Equals(publicKey.Oid)) { throw new Exception("RSA signature verification requires RSA public key"); } RSACryptoServiceProvider rsaKey = (RSACryptoServiceProvider)publicKey.Algorithm; if (hashAlgorithm == null) { // Before TLS 1.2 RSA signatures always used MD5+SHA1 // MD5+SHA1 is not supported by .NET, so we need custom code return TLSv1VerifyData(rsaKey, data, signature); } else { // Starting from TLS 1.2 the standard signature is used return rsaKey.VerifyData(data, hashAlgorithm, signature); } }