Beispiel #1
0
        private byte[] DeriveKey(BigInteger key, byte[] hash, char ch, int length) {
            byte[] result = new byte[length];

            SSH2DataWriter wr = new SSH2DataWriter();
            wr.WriteBigInteger(key);
            wr.Write(hash);
            wr.WriteByte((byte)ch);
            wr.Write(_sessionID);
            byte[] h1 = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray());
            if (h1.Length >= length) {
                Array.Copy(h1, 0, result, 0, length);
                return result;
            }
            else {
                wr = new SSH2DataWriter();
                wr.WriteBigInteger(key);
                wr.Write(_sessionID);
                wr.Write(h1);
                byte[] h2 = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray());
                if (h1.Length + h2.Length >= length) {
                    Array.Copy(h1, 0, result, 0, h1.Length);
                    Array.Copy(h2, 0, result, h1.Length, length - h1.Length);
                    return result;
                }
                else
                    throw new SSHException("necessary key length is too big"); //long key is not supported
            }
        }
Beispiel #2
0
        private byte[] WriteToDataWriter() {
            SSH2DataWriter wr = new SSH2DataWriter();
            wr.WriteString(SSH2Util.PublicKeyAlgorithmName(_hostkey.Algorithm));
            if (_hostkey.Algorithm == PublicKeyAlgorithm.RSA) {
                RSAPublicKey rsa = (RSAPublicKey)_hostkey;
                wr.WriteBigInteger(rsa.Exponent);
                wr.WriteBigInteger(rsa.Modulus);
            }
            else if (_hostkey.Algorithm == PublicKeyAlgorithm.DSA) {
                DSAPublicKey dsa = (DSAPublicKey)_hostkey;
                wr.WriteBigInteger(dsa.P);
                wr.WriteBigInteger(dsa.Q);
                wr.WriteBigInteger(dsa.G);
                wr.WriteBigInteger(dsa.Y);
            }
            else
                throw new SSHException("Host key algorithm is unsupported");

            return wr.ToByteArray();
        }
Beispiel #3
0
        private bool ProcessKEXDHREPLY(DataFragment packet) {
            //Round2 receives response
            SSH2DataReader re = null;
            PacketType h;
            do {
                re = new SSH2DataReader(packet);
                h = re.ReadPacketType();
                if (h == PacketType.SSH_MSG_KEXDH_REPLY)
                    break; //successfully exit
                else if (h == PacketType.SSH_MSG_IGNORE || h == PacketType.SSH_MSG_DEBUG) { //continue
                    packet = _connection.ReceivePacket();
                }
                else
                    throw new SSHException(String.Format("KeyExchange response is not KEXDH_REPLY but {0}", h));
            } while (true);

            byte[] key_and_cert = re.ReadString();
            BigInteger f = re.ReadMPInt();
            byte[] signature = re.ReadString();
            Debug.Assert(re.Rest == 0);

            //Round3 calc hash H
            SSH2DataWriter wr = new SSH2DataWriter();
            _k = f.modPow(_x, DH_PRIME);
            wr = new SSH2DataWriter();
            wr.WriteString(_cInfo._clientVersionString);
            wr.WriteString(_cInfo._serverVersionString);
            wr.WriteAsString(_clientKEXINITPayload);
            wr.WriteAsString(_serverKEXINITPayload);
            wr.WriteAsString(key_and_cert);
            wr.WriteBigInteger(_e);
            wr.WriteBigInteger(f);
            wr.WriteBigInteger(_k);
            _hash = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray());

            _connection.TraceReceptionEvent(h, "verifying host key");
            if (!VerifyHostKey(key_and_cert, signature, _hash))
                return false;

            //Debug.WriteLine("hash="+DebugUtil.DumpByteArray(hash));
            if (_sessionID == null)
                _sessionID = _hash;
            return true;
        }
Beispiel #4
0
 private DataFragment SendKEXDHINIT(Mode mode) {
     //Round1 computes and sends [e]
     byte[] sx = new byte[16];
     _param.Random.NextBytes(sx);
     _x = new BigInteger(sx);
     _e = new BigInteger(2).modPow(_x, DH_PRIME);
     SSH2DataWriter wr = new SSH2DataWriter();
     wr.WritePacketType(PacketType.SSH_MSG_KEXDH_INIT);
     wr.WriteBigInteger(_e);
     _status = Status.WAIT_KEXDH_REPLY;
     TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXDH_INIT, "");
     if (mode == Mode.Synchronized)
         return SynchronizedTransmitRawPayload(wr.ToByteArray());
     else {
         TransmitRawPayload(wr.ToByteArray());
         return null;
     }
 }
Beispiel #5
0
        // Tests signature verification using test vectors from NIST CAVP.
        // http://csrc.nist.gov/groups/STM/cavp/digital-signatures.html
        internal static void TestSignatureVerification() {
            using (var reader = new System.IO.StreamReader(@"186-3ecdsatestvectors\SigVer.rsp")) {
                EllipticCurve curve = null;
                byte[] msg = null;
                BigInteger qx = null;
                BigInteger qy = null;
                BigInteger r = null;
                BigInteger s = null;
                string result = null;
                int testCount = 0;

                while (true) {
                    string line = reader.ReadLine();
                    if (line == null) {
                        break;
                    }
                    var match = System.Text.RegularExpressions.Regex.Match(line, @"\[([-\w]+),(SHA-\d+)\]");
                    if (match.Success) {
                        string curveName = "nist" + match.Groups[1].Value.ToLowerInvariant().Replace("-", "");
                        curve = FindByName(curveName);
                        if (curve != null) {
                            using (var hashFunc = ECDSAHashAlgorithmChooser.Choose(curve)) {
                                var hashName = "SHA-" + hashFunc.HashSize.ToString();
                                if (hashName == match.Groups[2].Value) {
                                    Debug.WriteLine("Test " + curve.CurveName);
                                }
                                else {
                                    // hash function doesn't match
                                    curve = null;
                                }
                            }
                        }
                        msg = null;
                        qx = qy = r = s = null;
                        result = null;
                        testCount = 0;
                        continue;
                    }

                    if (line.StartsWith("Msg = ") && curve != null) {
                        msg = BigIntegerConverter.ParseHex(line.Substring(6).Trim());
                        continue;
                    }

                    if (line.StartsWith("Qx = ") && curve != null) {
                        qx = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim()));
                        continue;
                    }

                    if (line.StartsWith("Qy = ") && curve != null) {
                        qy = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim()));
                        continue;
                    }

                    if (line.StartsWith("R = ") && curve != null) {
                        r = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim()));
                        continue;
                    }

                    if (line.StartsWith("S = ") && curve != null) {
                        s = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim()));
                        continue;
                    }

                    if (line.StartsWith("Result = ") && curve != null) {
                        result = line.Substring(9, 1);

                        if (msg != null && qx != null && qy != null && r != null && s != null) {
                            var pk = new ECDSAPublicKey(curve, new ECPoint(qx, qy));
                            var buf = new SSH2DataWriter();
                            buf.WriteBigInteger(r);
                            buf.WriteBigInteger(s);
                            var sig = buf.ToByteArray();
                            string verRes;
                            try {
                                pk.Verify(sig, msg);
                                verRes = "P";
                            }
                            catch (VerifyException) {
                                verRes = "F";
                            }
                            if (verRes != result) {
                                throw new Exception("verification result doesn't match");
                            }
                            ++testCount;
                            Debug.WriteLine("Pass #{0}", testCount);
                        }

                        msg = null;
                        qx = qy = r = s = null;
                        result = null;
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Signing
        /// </summary>
        /// <param name="data">data to sign</param>
        /// <returns>signature blob</returns>
        public byte[] Sign(byte[] data) {
            BigInteger order = _curve.Order;

            byte[] hash = _publicKey.HashForSigning(data, _curve);
            BigInteger e = new BigInteger(hash);

            using (var rng = new RNGCryptoServiceProvider()) {

                BigInteger.ModulusRing nring = new BigInteger.ModulusRing(order);

                for (int tries = 0; tries < 10; ++tries) {
                    try {
                        ECDSAKeyPair tempKeyPair = _curve.GenerateKeyPair(rng);

                        BigInteger r = tempKeyPair.PublicKeyPoint.X % order;
                        if (r == 0) {
                            continue;
                        }

                        BigInteger k = tempKeyPair.PrivateKey;
                        BigInteger s = nring.Multiply(k.ModInverse(order), e + nring.Multiply(r, _privateKey));
                        if (s == 0) {
                            continue;
                        }

                        SSH2DataWriter writer = new SSH2DataWriter();
                        writer.WriteBigInteger(r);
                        writer.WriteBigInteger(s);

                        return writer.ToByteArray();
                    }
                    catch (Exception ex) {
                        Debug.WriteLine(ex);
                    }
                }
            }

            throw new SSHException(Strings.GetString("FailedSigning"));
        }
Beispiel #7
0
 private DataFragment SendKEXDHINIT(Mode mode)
 {
     //Round1 computes and sends [e]
     byte[] sx = new byte[32];
     RngManager.GetSecureRng().GetBytes(sx);
     _x = new BigInteger(sx);
     _e = new BigInteger(2).modPow(_x, GetDiffieHellmanPrime(_cInfo._kexAlgorithm));
     SSH2DataWriter wr = new SSH2DataWriter();
     wr.WritePacketType(PacketType.SSH_MSG_KEXDH_INIT);
     wr.WriteBigInteger(_e);
     _status = Status.WAIT_KEXDH_REPLY;
     TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXDH_INIT, "");
     if (mode == Mode.Synchronized)
         return SynchronizedTransmitRawPayload(wr.ToByteArray());
     else {
         TransmitRawPayload(wr.ToByteArray());
         return null;
     }
 }