SignedPkcs7.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //
  2. // SignedPkcs7.cs - System.Security.Cryptography.Pkcs.SignedPkcs7
  3. //
  4. // Author:
  5. // Sebastien Pouliot ([email protected])
  6. //
  7. // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
  8. //
  9. #if NET_1_2
  10. using System;
  11. using System.Security.Cryptography.X509Certificates;
  12. using System.Security.Cryptography.Xml;
  13. using System.Text;
  14. using Mono.Security;
  15. using Mono.Security.X509;
  16. namespace System.Security.Cryptography.Pkcs {
  17. public sealed class SignedPkcs7 {
  18. private ContentInfo _content;
  19. private bool _detached;
  20. private SignerInfoCollection _info;
  21. private X509CertificateExCollection _certs;
  22. private SubjectIdentifierType _type;
  23. private int _version;
  24. // constructors
  25. public SignedPkcs7 ()
  26. {
  27. _certs = new X509CertificateExCollection ();
  28. _info = new SignerInfoCollection ();
  29. }
  30. public SignedPkcs7 (ContentInfo content) : this (content, false) {}
  31. public SignedPkcs7 (ContentInfo content, bool detached) : this ()
  32. {
  33. if (content == null)
  34. throw new ArgumentNullException ("content");
  35. _content = content;
  36. _detached = detached;
  37. }
  38. public SignedPkcs7 (SubjectIdentifierType signerIdentifierType) : this ()
  39. {
  40. _type = signerIdentifierType;
  41. _version = ((_type == SubjectIdentifierType.SubjectKeyIdentifier) ? 2 : 0);
  42. }
  43. public SignedPkcs7 (SubjectIdentifierType signerIdentifierType, ContentInfo content) : this (content, false)
  44. {
  45. _type = signerIdentifierType;
  46. _version = ((_type == SubjectIdentifierType.SubjectKeyIdentifier) ? 2 : 0);
  47. }
  48. public SignedPkcs7 (SubjectIdentifierType signerIdentifierType, ContentInfo content, bool detached) : this (content, detached)
  49. {
  50. _type = signerIdentifierType;
  51. _version = ((_type == SubjectIdentifierType.SubjectKeyIdentifier) ? 2 : 0);
  52. }
  53. // properties
  54. public X509CertificateExCollection Certificates {
  55. get { return _certs; }
  56. }
  57. public ContentInfo ContentInfo {
  58. get {
  59. if (_content == null) {
  60. Oid oid = new Oid (PKCS7.data);
  61. _content = new ContentInfo (oid, new byte [0]);
  62. }
  63. return _content;
  64. }
  65. }
  66. public bool Detached {
  67. get { return _detached; }
  68. }
  69. public SignerInfoCollection SignerInfos {
  70. get { return _info; }
  71. }
  72. public int Version {
  73. get { return _version; }
  74. }
  75. // methods
  76. public void CheckSignature (bool verifySignatureOnly)
  77. {
  78. foreach (SignerInfo si in _info) {
  79. si.CheckSignature (verifySignatureOnly);
  80. }
  81. }
  82. public void CheckSignature (X509CertificateExCollection extraStore, bool verifySignatureOnly)
  83. {
  84. foreach (SignerInfo si in _info) {
  85. si.CheckSignature (extraStore, verifySignatureOnly);
  86. }
  87. }
  88. [MonoTODO]
  89. public void ComputeSignature ()
  90. {
  91. throw new CryptographicException ("");
  92. }
  93. [MonoTODO]
  94. public void ComputeSignature (Pkcs7Signer signer)
  95. {
  96. ComputeSignature ();
  97. }
  98. private string ToString (byte[] array)
  99. {
  100. StringBuilder sb = new StringBuilder ();
  101. foreach (byte b in array)
  102. sb.Append (b.ToString ("X2"));
  103. return sb.ToString ();
  104. }
  105. private byte[] GetKeyIdentifier (Mono.Security.X509.X509Certificate x509)
  106. {
  107. // if present in certificate return value of the SubjectKeyIdentifier
  108. Mono.Security.X509.X509Extension extn = x509.Extensions ["2.5.29.14"];
  109. if (extn != null) {
  110. ASN1 bs = new ASN1 (extn.Value.Value);
  111. return bs.Value;
  112. }
  113. // strangely DEPRECATED keyAttributes isn't used here (like KeyUsage)
  114. // if not then we must calculate the SubjectKeyIdentifier ourselve
  115. // Note: MS does that hash on the complete subjectPublicKeyInfo (unlike PKIX)
  116. // http://groups.google.ca/groups?selm=e7RqM%24plCHA.1488%40tkmsftngp02&oe=UTF-8&output=gplain
  117. ASN1 subjectPublicKeyInfo = new ASN1 (0x30);
  118. ASN1 algo = subjectPublicKeyInfo.Add (new ASN1 (0x30));
  119. algo.Add (new ASN1 (CryptoConfig.EncodeOID (x509.KeyAlgorithm)));
  120. // FIXME: does it work for DSA certs (without an 2.5.29.14 extension ?)
  121. algo.Add (new ASN1 (x509.KeyAlgorithmParameters));
  122. byte[] pubkey = x509.PublicKey;
  123. byte[] bsvalue = new byte [pubkey.Length + 1]; // add unused bits (0) before the public key
  124. Array.Copy (pubkey, 0, bsvalue, 1, pubkey.Length);
  125. subjectPublicKeyInfo.Add (new ASN1 (0x03, bsvalue));
  126. SHA1 sha = SHA1.Create ();
  127. return sha.ComputeHash (subjectPublicKeyInfo.GetBytes ());
  128. }
  129. [MonoTODO("incomplete - missing attributes")]
  130. public void Decode (byte[] encodedMessage)
  131. {
  132. PKCS7.ContentInfo ci = new PKCS7.ContentInfo (encodedMessage);
  133. if (ci.ContentType != PKCS7.signedData)
  134. throw new Exception ("");
  135. PKCS7.SignedData sd = new PKCS7.SignedData (ci.Content);
  136. SubjectIdentifierType type = SubjectIdentifierType.Unknown;
  137. object o = null;
  138. X509CertificateEx x509 = null;
  139. if (sd.SignerInfo.Certificate != null) {
  140. x509 = new X509CertificateEx (sd.SignerInfo.Certificate.RawData);
  141. }
  142. else if ((sd.SignerInfo.IssuerName != null) && (sd.SignerInfo.SerialNumber != null)) {
  143. byte[] serial = sd.SignerInfo.SerialNumber;
  144. Array.Reverse (serial); // ???
  145. type = SubjectIdentifierType.IssuerAndSerialNumber;
  146. X509IssuerSerial xis = new X509IssuerSerial ();
  147. xis.IssuerName = sd.SignerInfo.IssuerName;
  148. xis.SerialNumber = ToString (serial);
  149. o = xis;
  150. // TODO: move to a FindCertificate (issuer, serial, collection)
  151. foreach (Mono.Security.X509.X509Certificate x in sd.Certificates) {
  152. if (x.IssuerName == sd.SignerInfo.IssuerName) {
  153. if (ToString (x.SerialNumber) == xis.SerialNumber) {
  154. x509 = new X509CertificateEx (x.RawData);
  155. break;
  156. }
  157. }
  158. }
  159. }
  160. else if (sd.SignerInfo.SubjectKeyIdentifier != null) {
  161. string ski = ToString (sd.SignerInfo.SubjectKeyIdentifier);
  162. type = SubjectIdentifierType.SubjectKeyIdentifier;
  163. o = (object) ski;
  164. // TODO: move to a FindCertificate (ski, collection)
  165. foreach (Mono.Security.X509.X509Certificate x in sd.Certificates) {
  166. if (ToString (GetKeyIdentifier (x)) == ski) {
  167. x509 = new X509CertificateEx (x.RawData);
  168. break;
  169. }
  170. }
  171. }
  172. SignerInfo si = new SignerInfo (sd.SignerInfo.HashName, x509, type, o, sd.SignerInfo.Version);
  173. // si.AuthenticatedAttributes
  174. // si.UnauthenticatedAttributes
  175. _info.Add (si);
  176. ASN1 content = sd.ContentInfo.Content;
  177. Oid oid = new Oid (sd.ContentInfo.ContentType);
  178. _content = new ContentInfo (oid, content[0].Value);
  179. foreach (Mono.Security.X509.X509Certificate x in sd.Certificates) {
  180. _certs.Add (new X509CertificateEx (x.RawData));
  181. }
  182. _version = sd.Version;
  183. }
  184. [MonoTODO]
  185. public byte[] Encode ()
  186. {
  187. Mono.Security.X509.X509Certificate x509 = null;
  188. /* PKCS7.SignerInfo si = new PKCS7.SignerInfo ();
  189. switch (_type) {
  190. case SubjectIdentifierType.SubjectKeyIdentifier:
  191. si.SubjectKeyIdentifier = GetKeyIdentifier (x509);
  192. break;
  193. default:
  194. // SubjectIdentifierType.IssuerAndSerialNumber
  195. si.IssuerName = x509.IssuerName;
  196. si.SerialNumber = x509.SerialNumber;
  197. break;
  198. }
  199. PKCS7.SignedData sd = new PKCS7.SignedData ();
  200. sd.Version = _version;
  201. sd.SignerInfo = si;
  202. PKCS7.ContentInfo ci = new PKCS7.ContentInfo (PKCS7.signedData);
  203. ci.Content = sd.ASN1;
  204. return ci.GetBytes ();*/
  205. return null;
  206. }
  207. // counterSsignerInfo -> counterSignerInfo
  208. [MonoTODO]
  209. public void RemoveSignature (SignerInfo counterSsignerInfo)
  210. {
  211. }
  212. }
  213. }
  214. #endif