Author: spouliot
Date: 2007-05-09 12:50:33 -0400 (Wed, 09 May 2007)
New Revision: 77035
Modified:
trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog
trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs
Log:
* PKCS12.cs: Adds SecretBag support. Patch by Jay Miller.
Modified: trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog
===================================================================
--- trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog 2007-05-09
16:39:34 UTC (rev 77034)
+++ trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog 2007-05-09
16:50:33 UTC (rev 77035)
@@ -1,5 +1,6 @@
2007-05-09 Sebastien Pouliot <[EMAIL PROTECTED]>
+ * PKCS12.cs: Adds SecretBag support. Patch by Jay Miller.
* X509Certificate.cs: Fix IsCurrent (use UTC).
2006-12-14 Sebastien Pouliot <[EMAIL PROTECTED]>
Modified: trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs
===================================================================
--- trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs 2007-05-09
16:39:34 UTC (rev 77034)
+++ trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs 2007-05-09
16:50:33 UTC (rev 77035)
@@ -270,8 +270,10 @@
//private int _version;
private byte[] _password;
private ArrayList _keyBags;
+ private ArrayList _secretBags;
private X509CertificateCollection _certs;
private bool _keyBagsChanged;
+ private bool _secretBagsChanged;
private bool _certsChanged;
private int _iterations;
private ArrayList _safeBags;
@@ -283,8 +285,10 @@
{
_iterations = recommendedIterationCount;
_keyBags = new ArrayList ();
+ _secretBags = new ArrayList ();
_certs = new X509CertificateCollection ();
_keyBagsChanged = false;
+ _secretBagsChanged = false;
_certsChanged = false;
_safeBags = new ArrayList ();
}
@@ -505,6 +509,24 @@
}
}
+ public ArrayList Secrets {
+ get {
+ if (_secretBagsChanged) {
+ _secretBags.Clear ();
+ foreach (SafeBag sb in _safeBags) {
+ if (sb.BagOID.Equals
(secretBag)) {
+ ASN1 safeBag = sb.ASN1;
+ ASN1 bagValue = safeBag
[1];
+ byte[] secret =
bagValue.Value;
+ _secretBags.Add(secret);
+ }
+ }
+ _secretBagsChanged = false;
+ }
+ return ArrayList.ReadOnly(_secretBags);
+ }
+ }
+
public X509CertificateCollection Certificates {
get {
if (_certsChanged) {
@@ -741,7 +763,8 @@
// TODO
break;
case secretBag:
- // TODO
+ byte[] secret = bagValue.Value;
+ _secretBags.Add(secret);
break;
case safeContentsBag:
// TODO - ? recurse ?
@@ -936,6 +959,63 @@
return safeBag;
}
+ private ASN1 SecretBagSafeBag (byte[] secret, IDictionary
attributes)
+ {
+ ASN1 safeBag = new ASN1 (0x30);
+ safeBag.Add (ASN1Convert.FromOid (secretBag));
+ ASN1 bagValue = new ASN1 (0x80, secret);
+ 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 ASN1 CertificateSafeBag (X509Certificate x509,
IDictionary attributes)
{
ASN1 encapsulatedCertificate = new ASN1 (0x04,
x509.RawData);
@@ -1014,7 +1094,7 @@
return hmac.ComputeHash (data, 0, data.Length);
}
- /*
+ /*
* SafeContents ::= SEQUENCE OF SafeBag
*
* SafeBag ::= SEQUENCE {
@@ -1087,36 +1167,8 @@
}
if (certsSafeBag.Count > 0) {
- byte[] certsSalt = new byte [8];
- RNG.GetBytes (certsSalt);
-
- ASN1 seqParams = new ASN1 (0x30);
- seqParams.Add (new ASN1 (0x04,
certsSalt));
- seqParams.Add (ASN1Convert.FromInt32
(_iterations));
-
- ASN1 seqPbe = new ASN1 (0x30);
- seqPbe.Add (ASN1Convert.FromOid
(pbeWithSHAAnd3KeyTripleDESCBC));
- seqPbe.Add (seqParams);
-
- byte[] encrypted = Encrypt
(pbeWithSHAAnd3KeyTripleDESCBC, certsSalt, _iterations, certsSafeBag.GetBytes
());
- ASN1 encryptedCerts = new ASN1 (0x80,
encrypted);
-
- ASN1 seq = new ASN1 (0x30);
- seq.Add (ASN1Convert.FromOid
(PKCS7.Oid.data));
- seq.Add (seqPbe);
- seq.Add (encryptedCerts);
-
- ASN1 certsVersion = new ASN1 (0x02, new
byte [1] { 0x00 });
- ASN1 encData = new ASN1 (0x30);
- encData.Add (certsVersion);
- encData.Add (seq);
-
- ASN1 certsContent = new ASN1 (0xA0);
- certsContent.Add (encData);
-
- PKCS7.ContentInfo bag = new
PKCS7.ContentInfo (PKCS7.Oid.encryptedData);
- bag.Content = certsContent;
- safeBagSequence.Add (bag.ASN1);
+ PKCS7.ContentInfo contentInfo =
EncryptedContentInfo (certsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
+ safeBagSequence.Add (contentInfo.ASN1);
}
}
@@ -1138,7 +1190,22 @@
}
}
+ // Doing SecretBags separately in case we want to
change their encryption independently.
+ if (_safeBags.Count > 0) {
+ ASN1 secretsSafeBag = new ASN1 (0x30);
+ foreach (SafeBag sb in _safeBags) {
+ if (sb.BagOID.Equals (secretBag)) {
+ secretsSafeBag.Add (sb.ASN1);
+ }
+ }
+ if (secretsSafeBag.Count > 0) {
+ PKCS7.ContentInfo contentInfo =
EncryptedContentInfo (secretsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
+ safeBagSequence.Add (contentInfo.ASN1);
+ }
+ }
+
+
ASN1 encapsulates = new ASN1 (0x04,
safeBagSequence.GetBytes ());
ASN1 ci = new ASN1 (0xA0);
ci.Add (encapsulates);
@@ -1177,6 +1244,41 @@
return pfx.GetBytes ();
}
+ // Creates an encrypted PKCS#7 ContentInfo with safeBags as its
SafeContents. Used in GetBytes(), above.
+ private PKCS7.ContentInfo EncryptedContentInfo(ASN1 safeBags,
string algorithmOid)
+ {
+ byte[] salt = new byte [8];
+ RNG.GetBytes (salt);
+
+ ASN1 seqParams = new ASN1 (0x30);
+ seqParams.Add (new ASN1 (0x04, salt));
+ seqParams.Add (ASN1Convert.FromInt32 (_iterations));
+
+ ASN1 seqPbe = new ASN1 (0x30);
+ seqPbe.Add (ASN1Convert.FromOid (algorithmOid));
+ seqPbe.Add (seqParams);
+
+ byte[] encrypted = Encrypt (algorithmOid, salt,
_iterations, safeBags.GetBytes ());
+ ASN1 encryptedContent = new ASN1 (0x80, encrypted);
+
+ ASN1 seq = new ASN1 (0x30);
+ seq.Add (ASN1Convert.FromOid (PKCS7.Oid.data));
+ seq.Add (seqPbe);
+ seq.Add (encryptedContent);
+
+ ASN1 version = new ASN1 (0x02, new byte [1] { 0x00 });
+ ASN1 encData = new ASN1 (0x30);
+ encData.Add (version);
+ encData.Add (seq);
+
+ ASN1 finalContent = new ASN1 (0xA0);
+ finalContent.Add (encData);
+
+ PKCS7.ContentInfo bag = new PKCS7.ContentInfo
(PKCS7.Oid.encryptedData);
+ bag.Content = finalContent;
+ return bag;
+ }
+
public void AddCertificate (X509Certificate cert)
{
AddCertificate (cert, null);
@@ -1457,7 +1559,57 @@
}
}
+ public void AddSecretBag (byte[] secret)
+ {
+ AddSecretBag (secret, null);
+ }
+ public void AddSecretBag (byte[] secret, IDictionary attributes)
+ {
+ bool found = false;
+
+ for (int i = 0; !found && i < _safeBags.Count; i++) {
+ SafeBag sb = (SafeBag)_safeBags [i];
+
+ if (sb.BagOID.Equals (secretBag)) {
+ ASN1 bagValue = sb.ASN1 [1];
+ byte[] ssecret = bagValue.Value;
+
+ if (Compare (secret, ssecret)) {
+ found = true;
+ }
+ }
+ }
+
+ if (!found) {
+ _safeBags.Add (new SafeBag (secretBag,
SecretBagSafeBag (secret, attributes)));
+ _secretBagsChanged = true;
+ }
+ }
+
+ public void RemoveSecretBag (byte[] secret)
+ {
+ int sIndex = -1;
+
+ for (int i = 0; sIndex == -1 && i < _safeBags.Count;
i++) {
+ SafeBag sb = (SafeBag)_safeBags [i];
+
+ if (sb.BagOID.Equals (secretBag)) {
+ ASN1 bagValue = sb.ASN1 [1];
+ byte[] ssecret = bagValue.Value;
+
+ if (Compare (secret, ssecret)) {
+ sIndex = i;
+ }
+ }
+ }
+
+ if (sIndex != -1) {
+ _safeBags.RemoveAt (sIndex);
+ _secretBagsChanged = true;
+ }
+ }
+
public AsymmetricAlgorithm GetAsymmetricAlgorithm (IDictionary
attrs)
{
foreach (SafeBag sb in _safeBags) {
@@ -1539,6 +1691,52 @@
return null;
}
+ public byte[] GetSecret (IDictionary attrs)
+ {
+ foreach (SafeBag sb in _safeBags) {
+ if (sb.BagOID.Equals (secretBag)) {
+ 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];
+ return bagValue.Value;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
public X509Certificate GetCertificate (IDictionary attrs)
{
foreach (SafeBag sb in _safeBags) {
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches