Beispiel #1
0
		public void EncryptedPrivateKey_Farscape () 
		{
			Assert.AreEqual (PKCS8.KeyInfo.EncryptedPrivateKey, PKCS8.GetType (pkcs8_der), "PKCS8.GetType");
			PKCS8.EncryptedPrivateKeyInfo p8 = new PKCS8.EncryptedPrivateKeyInfo (pkcs8_der);
			Assert.AreEqual ("1.2.840.113549.1.12.1.3", p8.Algorithm, "Algorithm");
			Assert.AreEqual ("90-14-B5-F0-B6-86-56-CB-FA-63-AD-9F-5A-59-6C-AD-00-3C-37-8A-C3-88-58-8B-D7-48-53-7A-C8-5B-0D-98-DD-8B-B3-EC-4C-AC-61-18-E3-5E-47-AD-C7-92-BC-D3-00-07-FF-1A-68-74-45-8E-D8-7C-9F-18-7B-D7-C8-47-BA-6B-19-F2-BF-7E-51-0B-4B-43-E8-B9-56-7E-D0-74-C7-DE-76-DB-FF-5C-6B-53-BE-31-06-AE-6C-8F-DC-49-04-71-74-EE-B8-06-CB-AD-86-B4-4E-B9-46-A1-03-5E-0E-A7-C7-37-6B-B0-8D-2D-81-1F-E3-C2-05-DE-EF-51-07-70-6E-35-9A-AD-19-5E-AF-EB-7F-EF-E4-AB-07-F3-F6-EA-FA-0E-83-65-06-3C-F3-BD-96-08-14-C5-34-26-ED-C0-10-CC-AE-2D-8F-BE-ED-98-0D-88-1B-1E-C7-37-F0-FC-DB-3C-E3-1B-66-52-45-6E-05-A6-D9-12-23-05-5F-E3-9F-7D-21-9B-2E-3E-9E-3C-EE-D1-9B-55-DE-57-60-A5-24-2D-C7-94-EC-FC-B1-6A-65-BD-85-02-5C-58-AA-5A-6A-F3-AC-6B-DD-0E-63-B2-4B-5B-67-3D-C3-BF-E4-C8-EF-3F-89-5A-CD-6D-EF-05-22-2B-72-FF-80-7A-DD-F1-59-A7-6F-00-B1-BD-4D-88-D6-E4-8A-DD-A9-FC-D9-01-0A-65-8E-52-F9-7E-20-72-67-0D-5B-EE-67-5B-46-4A-15-A2-6F-15-2B-5B-9A-93-12-4F-F4-AD-49-D0-11-F1-7E-40-DE-32-96-2E-B3-E8-71-60-27-6E-A2-71-83-C7-FE-0E-8B-31-06-64-E1-19-02-B9-44-25-0C-94-64-7E-5F-89-4D-7E-99-0B-91-B8-22-A5-33-92-D3-49-07-1D-C6-25-4A-D7-6D-E2-94-3F-FA-10-72-59-62-F5-C6-D4-3A-EE-8F-BC-9C-BC-FC-C7-37-BF-7C-A0-67-B0-FF-0F-29-A0-A2-71-6B-21-00-F4-54-D9-3D-1B-CE-F4-FE-6F-F5-21-CB-47-58-17-F6-45-2F-A0-3B-8B-D9-B8-8A-33-3F-16-E0-C7-8A-B8-11-2F-A8-7E-7D-A7-7B-65-27-89-3C-67-4D-D5-70-28-76-60-96-68-BF-FB-CD-49-E0-8A-7C-6F-76-06-48-6D-63-67-8A-47-82-5E-7F-0E-AC-46-B6-BC-0A-6D-E2-1A-3A-20-A5-C7-81-71-6E-2B-16-97-D4-FA-C0-DD-72-5B-9F-A3-43-F4-85-B1-C6-A8-E0-62-81-5D-A5-07-29-6A-6A-2D-E1-1D-BE-12-6D-42-58-6F-4E-30-3D-BF-32-11-38-BC-36-76-60-FC-57-2F-D3-9E-C4-1A-92-EA-DE-85-FD-E7-AA-30-A6-97-2C-36-3B-3B-0E-92-52-FF-42-D7-62-6C-C1-3A-E7-1B-4E-13-8C-95-B3-4B-A7-9E-42-75-A8-CA-63-76-C4-45-74-96-43-D8-86-82-BE-37-FF-9B-EB-B7-18-A1-2F-E3-6C-08-E8-11-96-8C-5E-9E-2B-E7-DB-7D-54-E1-DB-1E-D3-8F-B5-19-4B-B2-16-DB-CF-EC-88-0B-6C-3C-E4-F2-C4-FF-4D-3E-53-52-3A-81-0B-6E-AC-95-EA-5A-6E-4D-83-23-82-C9-90-02-74-10-2A-6C-FB-97-4F-5F-70-8E-F0-B9", BitConverter.ToString (p8.EncryptedData), 
				"EncryptedData");
			Assert.AreEqual ("86-2A-A9-71-6D-A4-B8-2D", BitConverter.ToString (p8.Salt), "Salt");
			Assert.AreEqual (2000, p8.IterationCount, "IterationCount");
		}
		private ASN1 Pkcs8ShroudedKeyBagSafeBag (AsymmetricAlgorithm aa, IDictionary attributes) 
		{
			PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo ();
			if (aa is RSA) {
				pki.Algorithm = "1.2.840.113549.1.1.1";
				pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((RSA)aa);
			}
			else if (aa is DSA) {
				pki.Algorithm = null;
				pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((DSA)aa);
			}
			else
				throw new CryptographicException ("Unknown asymmetric algorithm {0}", aa.ToString ());

			PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo ();
			epki.Algorithm = pbeWithSHAAnd3KeyTripleDESCBC;
			epki.IterationCount = _iterations;
			epki.EncryptedData = Encrypt (pbeWithSHAAnd3KeyTripleDESCBC, epki.Salt, _iterations, pki.GetBytes ());

			ASN1 safeBag = new ASN1 (0x30);
			safeBag.Add (ASN1Convert.FromOid (pkcs8ShroudedKeyBag));
			ASN1 bagValue = new ASN1 (0xA0);
			bagValue.Add (new ASN1 (epki.GetBytes ()));
			safeBag.Add (bagValue);

			if (attributes != null) {
				ASN1 bagAttributes = new ASN1 (0x31);
				IDictionaryEnumerator de = attributes.GetEnumerator ();

				while (de.MoveNext ()) {
					string oid = (string)de.Key;
					switch (oid) {
					case PKCS9.friendlyName:
						ArrayList names = (ArrayList)de.Value;
						if (names.Count > 0) {
							ASN1 pkcs12Attribute = new ASN1 (0x30);
							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
							ASN1 attrValues = new ASN1 (0x31);
							foreach (byte[] name in names) {
								ASN1 attrValue = new ASN1 (0x1e);
								attrValue.Value = name;
								attrValues.Add (attrValue);
							}
							pkcs12Attribute.Add (attrValues);
							bagAttributes.Add (pkcs12Attribute);
						}
						break;
					case PKCS9.localKeyId:
						ArrayList keys = (ArrayList)de.Value;
						if (keys.Count > 0) {
							ASN1 pkcs12Attribute = new ASN1 (0x30);
							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
							ASN1 attrValues = new ASN1 (0x31);
							foreach (byte[] key in keys) {
								ASN1 attrValue = new ASN1 (0x04);
								attrValue.Value = key;
								attrValues.Add (attrValue);
							}
							pkcs12Attribute.Add (attrValues);
							bagAttributes.Add (pkcs12Attribute);
						}
						break;
					default:
						break;
					}
				}

				if (bagAttributes.Count > 0) {
					safeBag.Add (bagAttributes);
				}
			}

			return safeBag;
		}
		private void ReadSafeBag (ASN1 safeBag) 
		{
			if (safeBag.Tag != 0x30)
				throw new ArgumentException ("invalid safeBag");

			ASN1 bagId = safeBag [0];
			if (bagId.Tag != 0x06)
				throw new ArgumentException ("invalid safeBag id");

			ASN1 bagValue = safeBag [1];
			string oid = ASN1Convert.ToOid (bagId);
			switch (oid) {
				case keyBag:
					// NEED UNIT TEST
					AddPrivateKey (new PKCS8.PrivateKeyInfo (bagValue.Value));
					break;
				case pkcs8ShroudedKeyBag:
					PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
					byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
					AddPrivateKey (new PKCS8.PrivateKeyInfo (decrypted));
					Array.Clear (decrypted, 0, decrypted.Length);
					break;
				case certBag:
					PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
					if (cert.ContentType != x509Certificate)
						throw new NotSupportedException ("unsupport certificate type");
					X509Certificate x509 = new X509Certificate (cert.Content [0].Value);
					_certs.Add (x509);
					break;
				case crlBag:
					// TODO
					break;
				case secretBag: 
					// TODO
					break;
				case safeContentsBag:
					// TODO - ? recurse ?
					break;
				default:
					throw new ArgumentException ("unknown safeBag oid");
			}

			if (safeBag.Count > 2) {
				ASN1 bagAttributes = safeBag [2];
				if (bagAttributes.Tag != 0x31)
					throw new ArgumentException ("invalid safeBag attributes id");

				for (int i = 0; i < bagAttributes.Count; i++) {
					ASN1 pkcs12Attribute = bagAttributes[i];
						
					if (pkcs12Attribute.Tag != 0x30)
						throw new ArgumentException ("invalid PKCS12 attributes id");

					ASN1 attrId = pkcs12Attribute [0];
					if (attrId.Tag != 0x06)
						throw new ArgumentException ("invalid attribute id");
						
					string attrOid = ASN1Convert.ToOid (attrId);

					ASN1 attrValues = pkcs12Attribute[1];
					for (int j = 0; j < attrValues.Count; j++) {
						ASN1 attrValue = attrValues[j];

						switch (attrOid) {
						case PKCS9.friendlyName:
							if (attrValue.Tag != 0x1e)
								throw new ArgumentException ("invalid attribute value id");
							break;
						case PKCS9.localKeyId:
							if (attrValue.Tag != 0x04)
								throw new ArgumentException ("invalid attribute value id");
							break;
						default:
							// Unknown OID -- don't check Tag
							break;
						}
					}
				}
			}

			_safeBags.Add (new SafeBag(oid, safeBag));
		}
		public IDictionary GetAttributes (AsymmetricAlgorithm aa)
		{
			IDictionary result = new Hashtable ();

			foreach (SafeBag sb in _safeBags) {
				if (sb.BagOID.Equals (keyBag) || sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
					ASN1 safeBag = sb.ASN1;

					ASN1 bagValue = safeBag [1];
					AsymmetricAlgorithm saa = null;
					if (sb.BagOID.Equals (keyBag)) {
						PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
						byte[] privateKey = pki.PrivateKey;
						switch (privateKey [0]) {
						case 0x02:
							DSAParameters p = new DSAParameters (); // FIXME
							saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
							break;
						case 0x30:
							saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
							break;
						default:
							break;
						}
						Array.Clear (privateKey, 0, privateKey.Length);
					} else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
						PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
						byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
						PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
						byte[] privateKey = pki.PrivateKey;
						switch (privateKey [0]) {
						case 0x02:
							DSAParameters p = new DSAParameters (); // FIXME
							saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
							break;
						case 0x30:
							saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
							break;
						default:
							break;
						}
						Array.Clear (privateKey, 0, privateKey.Length);
						Array.Clear (decrypted, 0, decrypted.Length);
					}

					if (saa != null && CompareAsymmetricAlgorithm (saa, aa)) {
						if (safeBag.Count == 3) {
							ASN1 bagAttributes = safeBag [2];
							
							for (int i = 0; i < bagAttributes.Count; i++) {
								ASN1 pkcs12Attribute = bagAttributes [i];
								ASN1 attrId = pkcs12Attribute [0];
								string aOid = ASN1Convert.ToOid (attrId);
								ArrayList aValues = new ArrayList ();

								ASN1 attrValues = pkcs12Attribute [1];
									
								for (int j = 0; j < attrValues.Count; j++) {
									ASN1 attrValue = attrValues [j];
									aValues.Add (attrValue.Value);
								}
								result.Add (aOid, aValues);
							}
						}
					}
				}
			}

			return result;
		}
		public AsymmetricAlgorithm GetAsymmetricAlgorithm (IDictionary attrs)
		{
			foreach (SafeBag sb in _safeBags) {
				if (sb.BagOID.Equals (keyBag) || sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
					ASN1 safeBag = sb.ASN1;

					if (safeBag.Count == 3) {
						ASN1 bagAttributes = safeBag [2];

						int bagAttributesFound = 0;
						for (int i = 0; i < bagAttributes.Count; i++) {
							ASN1 pkcs12Attribute = bagAttributes [i];
							ASN1 attrId = pkcs12Attribute [0];
							string ao = ASN1Convert.ToOid (attrId);
							ArrayList dattrValues = (ArrayList)attrs [ao];

							if (dattrValues != null) {
								ASN1 attrValues = pkcs12Attribute [1];

								if (dattrValues.Count == attrValues.Count) {
									int attrValuesFound = 0;
									for (int j = 0; j < attrValues.Count; j++) {
										ASN1 attrValue = attrValues [j];
										byte[] value = (byte[])dattrValues [j];
									
										if (Compare (value, attrValue.Value)) {
											attrValuesFound += 1;
										}
									}
									if (attrValuesFound == attrValues.Count) {
										bagAttributesFound += 1;
									}
								}
							}
						}
						if (bagAttributesFound == bagAttributes.Count) {
							ASN1 bagValue = safeBag [1];
							AsymmetricAlgorithm aa = null;
							if (sb.BagOID.Equals (keyBag)) {
								PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
								byte[] privateKey = pki.PrivateKey;
								switch (privateKey [0]) {
								case 0x02:
									DSAParameters p = new DSAParameters (); // FIXME
									aa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
									break;
								case 0x30:
									aa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
									break;
								default:
									break;
								}
								Array.Clear (privateKey, 0, privateKey.Length);
							} else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
								PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
								byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
								PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
								byte[] privateKey = pki.PrivateKey;
								switch (privateKey [0]) {
								case 0x02:
									DSAParameters p = new DSAParameters (); // FIXME
									aa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
									break;
								case 0x30:
									aa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
									break;
								default:
									break;
								}
								Array.Clear (privateKey, 0, privateKey.Length);
								Array.Clear (decrypted, 0, decrypted.Length);
							}
							return aa;
						}
					}
				}
			}

			return null;
		}
		public void RemovePkcs8ShroudedKeyBag (AsymmetricAlgorithm aa)
		{
			int aaIndex = -1;

			for (int i = 0; aaIndex == -1 && i < _safeBags.Count; i++) {
				SafeBag sb = (SafeBag)_safeBags [i];

				if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
					ASN1 bagValue = sb.ASN1 [1];
					PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
					byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
					PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
					byte[] privateKey = pki.PrivateKey;

					AsymmetricAlgorithm saa = null;
					switch (privateKey [0]) {
					case 0x02:
						DSAParameters p = new DSAParameters (); // FIXME
						saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
						break;
					case 0x30:
						saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
						break;
					default:
						Array.Clear (decrypted, 0, decrypted.Length);
						Array.Clear (privateKey, 0, privateKey.Length);
						throw new CryptographicException ("Unknown private key format");
					}

					Array.Clear (decrypted, 0, decrypted.Length);
					Array.Clear (privateKey, 0, privateKey.Length);

					if (CompareAsymmetricAlgorithm (aa, saa)) {
						aaIndex = i;
					}
				}
			}

			if (aaIndex != -1) {
				_safeBags.RemoveAt (aaIndex);
				_keyBagsChanged = true;
			}
		}