Пример #1
0
 public void TestNonIntegerTag()
 {
     using (MemoryStream mem = new MemoryStream(
                new byte[] { 0x30, 0x03, 0x02, 0x01, 0x01 }
                )) {
         BERReader  reader = new BERReader(mem);
         BigInteger n;
         Assert.False(reader.ReadInteger(out n));
     }
 }
Пример #2
0
 public void TestIncompleteIntegerTag()
 {
     using (MemoryStream mem = new MemoryStream(
                new byte[] { 0x02, 0x04, 0x12, 0x34, 0x56 }
                )) {
         BERReader  reader = new BERReader(mem);
         BigInteger n;
         Assert.False(reader.ReadInteger(out n));
     }
 }
Пример #3
0
 public void TestIncompleteTag()
 {
     using (MemoryStream mem = new MemoryStream(
                new byte[] { 0x7f, 0x87, 0xef, 0xab, 0xb7, 0x6e }
                )) {
         BERReader            reader  = new BERReader(mem);
         BERReader.BERTagInfo tagInfo = new BERReader.BERTagInfo();
         Assert.False(reader.ReadTagInfo(ref tagInfo));
     }
 }
Пример #4
0
 public void TestIntegerTag4()
 {
     using (MemoryStream mem = new MemoryStream(
                new byte[] { 0x02, 0x09, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x01 }
                )) {
         BERReader  reader = new BERReader(mem);
         BigInteger n;
         Assert.True(reader.ReadInteger(out n));
         Assert.AreEqual("123456789ABCDEF001", n.ToString(16));
     }
 }
Пример #5
0
 public void TestIntegerTag3()
 {
     using (MemoryStream mem = new MemoryStream(
                new byte[] { 0x02, 0x01, 0x00 }
                )) {
         BERReader  reader = new BERReader(mem);
         BigInteger n;
         Assert.True(reader.ReadInteger(out n));
         Assert.AreEqual("0", n.ToString());
     }
 }
Пример #6
0
 public void TestLargeTag()
 {
     using (MemoryStream mem = new MemoryStream(
                new byte[] { 0x7f, 0x87, 0xef, 0xab, 0xb7, 0x6e, 0x03, 0x02, 0x01, 0x01 }
                )) {
         BERReader            reader  = new BERReader(mem);
         BERReader.BERTagInfo tagInfo = new BERReader.BERTagInfo();
         Assert.True(reader.ReadTagInfo(ref tagInfo));
         Assert.AreEqual(1, tagInfo.ClassBits);
         Assert.AreEqual(true, tagInfo.IsConstructed);
         Assert.AreEqual(0x7deadbee, tagInfo.TagNumber);
         Assert.AreEqual(3, tagInfo.Length);
     }
 }
Пример #7
0
		/// <summary>
		/// Read OpenSSH SSH2 private key parameters.
		/// </summary>
		/// <param name="passphrase">passphrase for decrypt the key file</param>
		/// <param name="keyPair">key pair</param>
		/// <param name="comment">comment or empty if it didn't exist</param>
		public void Load(string passphrase, out KeyPair keyPair, out string comment) {
			if (keyFile == null)
				throw new SSHException("A key file is not loaded yet");

			KeyType keyType;
			String base64Text;
			bool encrypted = false;
			CipherAlgorithm? encryption = null;
			byte[] iv = null;
			int keySize = 0;
			int ivSize = 0;
			using (StreamReader sreader = GetStreamReader()) {
				string line = sreader.ReadLine();
				if (line == null)
					throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected eof)");

				if (line == PrivateKeyFileHeader.SSH2_OPENSSH_HEADER_RSA)
					keyType = KeyType.RSA;
				else if (line == PrivateKeyFileHeader.SSH2_OPENSSH_HEADER_DSA)
					keyType = KeyType.DSA;
				else
					throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected key type)");

				string footer = line.Replace("BEGIN", "END");

				StringBuilder buf = new StringBuilder();
				comment = String.Empty;
				while (true) {
					line = sreader.ReadLine();
					if (line == null)
						throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected eof)");
					if (line == footer)
						break;
					if (line.IndexOf(':') >= 0) {
						if (line.StartsWith("Proc-Type:")) {
							string[] w = line.Substring("Proc-Type:".Length).Trim().Split(',');
							if (w.Length < 1)
								throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid Proc-Type)");
							if (w[0] != "4")
								throw new SSHException(Strings.GetString("UnsupportedPrivateKeyFormat")
											+ " (" + Strings.GetString("Reason_UnsupportedProcType") + ")");
							if (w.Length >= 2 && w[1] == "ENCRYPTED")
								encrypted = true;
						}
						else if (line.StartsWith("DEK-Info:")) {
							string[] w = line.Substring("DEK-Info:".Length).Trim().Split(',');
							if (w.Length < 2)
								throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid DEK-Info)");
							switch(w[0]) {
								case "DES-EDE3-CBC":
									encryption = CipherAlgorithm.TripleDES;
									ivSize = 8;
									keySize = 24;
									break;
								case "AES-128-CBC":
									encryption = CipherAlgorithm.AES128;
									ivSize = 16;
									keySize = 16;
									break;
								default:
									throw new SSHException(Strings.GetString("UnsupportedPrivateKeyFormat")
											+ " (" + Strings.GetString("Reason_UnsupportedEncryptionType") + ")");
							}
							iv = HexToByteArray(w[1]);
							if (iv == null || iv.Length != ivSize)
								throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid IV)");
						}
					}
					else
						buf.Append(line);
				}
				base64Text = buf.ToString();
			}

			byte[] keydata = Base64.Decode(Encoding.ASCII.GetBytes(base64Text));

			if (encrypted) {
				if (!encryption.HasValue || iv == null)
					throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (missing encryption type or IV)");
				byte[] key = OpenSSHPassphraseToKey(passphrase, iv, keySize);
				Cipher cipher = CipherFactory.CreateCipher(SSHProtocol.SSH2, encryption.Value, key, iv);
				if (keydata.Length % cipher.BlockSize != 0)
					throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid key data size)");
				cipher.Decrypt(keydata, 0, keydata.Length, keydata, 0);
			}

			using (MemoryStream keyDataStream = new MemoryStream(keydata, false)) {
				BERReader reader = new BERReader(keyDataStream);
				if (!reader.ReadSequence())
					throw new SSHException(Strings.GetString("WrongPassphrase"));
				if (keyType == KeyType.RSA) {
					/* from OpenSSL rsa_asn1.c
					 * 
					 * ASN1_SIMPLE(RSA, version, LONG),
					 * ASN1_SIMPLE(RSA, n, BIGNUM),
					 * ASN1_SIMPLE(RSA, e, BIGNUM),
					 * ASN1_SIMPLE(RSA, d, BIGNUM),
					 * ASN1_SIMPLE(RSA, p, BIGNUM),
					 * ASN1_SIMPLE(RSA, q, BIGNUM),
					 * ASN1_SIMPLE(RSA, dmp1, BIGNUM),
					 * ASN1_SIMPLE(RSA, dmq1, BIGNUM),
					 * ASN1_SIMPLE(RSA, iqmp, BIGNUM)
					 */
					BigInteger v, n, e, d, p, q, dmp1, dmq1, iqmp;
					if (!reader.ReadInteger(out v) ||
						!reader.ReadInteger(out n) ||
						!reader.ReadInteger(out e) ||
						!reader.ReadInteger(out d) ||
						!reader.ReadInteger(out p) ||
						!reader.ReadInteger(out q) ||
						!reader.ReadInteger(out dmp1) ||
						!reader.ReadInteger(out dmq1) ||
						!reader.ReadInteger(out iqmp)) {

						throw new SSHException(Strings.GetString("WrongPassphrase"));
					}

					BigInteger u = p.modInverse(q);	// inverse of p mod q
					keyPair = new RSAKeyPair(e, d, n, u, p, q);
				}
				else if (keyType == KeyType.DSA) {
					/* from OpenSSL dsa_asn1.c
					 * 
					 * ASN1_SIMPLE(DSA, version, LONG),
					 * ASN1_SIMPLE(DSA, p, BIGNUM),
					 * ASN1_SIMPLE(DSA, q, BIGNUM),
					 * ASN1_SIMPLE(DSA, g, BIGNUM),
					 * ASN1_SIMPLE(DSA, pub_key, BIGNUM),
					 * ASN1_SIMPLE(DSA, priv_key, BIGNUM)
					 */
					BigInteger v, p, q, g, y, x;
					if (!reader.ReadInteger(out v) ||
						!reader.ReadInteger(out p) ||
						!reader.ReadInteger(out q) ||
						!reader.ReadInteger(out g) ||
						!reader.ReadInteger(out y) ||
						!reader.ReadInteger(out x)) {

						throw new SSHException(Strings.GetString("WrongPassphrase"));
					}
					keyPair = new DSAKeyPair(p, g, q, y, x);
				}
				else {
					throw new SSHException("Unknown file type. This should not happen.");
				}
			}
		}