KeyAgreeRecipientInformation.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms.Ecc;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Utilities;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  12. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
  13. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  14. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  15. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  16. using BestHTTP.SecureProtocol.Org.BouncyCastle.Pkcs;
  17. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  18. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
  19. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
  20. {
  21. /**
  22. * the RecipientInfo class for a recipient who has been sent a message
  23. * encrypted using key agreement.
  24. */
  25. public class KeyAgreeRecipientInformation
  26. : RecipientInformation
  27. {
  28. private KeyAgreeRecipientInfo info;
  29. private Asn1OctetString encryptedKey;
  30. internal static void ReadRecipientInfo(IList infos, KeyAgreeRecipientInfo info,
  31. CmsSecureReadable secureReadable)
  32. {
  33. try
  34. {
  35. foreach (Asn1Encodable rek in info.RecipientEncryptedKeys)
  36. {
  37. RecipientEncryptedKey id = RecipientEncryptedKey.GetInstance(rek.ToAsn1Object());
  38. RecipientID rid = new RecipientID();
  39. Asn1.Cms.KeyAgreeRecipientIdentifier karid = id.Identifier;
  40. Asn1.Cms.IssuerAndSerialNumber iAndSN = karid.IssuerAndSerialNumber;
  41. if (iAndSN != null)
  42. {
  43. rid.Issuer = iAndSN.Name;
  44. rid.SerialNumber = iAndSN.SerialNumber.Value;
  45. }
  46. else
  47. {
  48. Asn1.Cms.RecipientKeyIdentifier rKeyID = karid.RKeyID;
  49. // Note: 'date' and 'other' fields of RecipientKeyIdentifier appear to be only informational
  50. rid.SubjectKeyIdentifier = rKeyID.SubjectKeyIdentifier.GetOctets();
  51. }
  52. infos.Add(new KeyAgreeRecipientInformation(info, rid, id.EncryptedKey,
  53. secureReadable));
  54. }
  55. }
  56. catch (IOException e)
  57. {
  58. throw new ArgumentException("invalid rid in KeyAgreeRecipientInformation", e);
  59. }
  60. }
  61. internal KeyAgreeRecipientInformation(
  62. KeyAgreeRecipientInfo info,
  63. RecipientID rid,
  64. Asn1OctetString encryptedKey,
  65. CmsSecureReadable secureReadable)
  66. : base(info.KeyEncryptionAlgorithm, secureReadable)
  67. {
  68. this.info = info;
  69. this.rid = rid;
  70. this.encryptedKey = encryptedKey;
  71. }
  72. private AsymmetricKeyParameter GetSenderPublicKey(
  73. AsymmetricKeyParameter receiverPrivateKey,
  74. OriginatorIdentifierOrKey originator)
  75. {
  76. OriginatorPublicKey opk = originator.OriginatorPublicKey;
  77. if (opk != null)
  78. {
  79. return GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, opk);
  80. }
  81. OriginatorID origID = new OriginatorID();
  82. Asn1.Cms.IssuerAndSerialNumber iAndSN = originator.IssuerAndSerialNumber;
  83. if (iAndSN != null)
  84. {
  85. origID.Issuer = iAndSN.Name;
  86. origID.SerialNumber = iAndSN.SerialNumber.Value;
  87. }
  88. else
  89. {
  90. SubjectKeyIdentifier ski = originator.SubjectKeyIdentifier;
  91. origID.SubjectKeyIdentifier = ski.GetKeyIdentifier();
  92. }
  93. return GetPublicKeyFromOriginatorID(origID);
  94. }
  95. private AsymmetricKeyParameter GetPublicKeyFromOriginatorPublicKey(
  96. AsymmetricKeyParameter receiverPrivateKey,
  97. OriginatorPublicKey originatorPublicKey)
  98. {
  99. PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(receiverPrivateKey);
  100. SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(
  101. privInfo.PrivateKeyAlgorithm,
  102. originatorPublicKey.PublicKey.GetBytes());
  103. return PublicKeyFactory.CreateKey(pubInfo);
  104. }
  105. private AsymmetricKeyParameter GetPublicKeyFromOriginatorID(
  106. OriginatorID origID)
  107. {
  108. // TODO Support all alternatives for OriginatorIdentifierOrKey
  109. // see RFC 3852 6.2.2
  110. throw new CmsException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier");
  111. }
  112. private KeyParameter CalculateAgreedWrapKey(
  113. string wrapAlg,
  114. AsymmetricKeyParameter senderPublicKey,
  115. AsymmetricKeyParameter receiverPrivateKey)
  116. {
  117. DerObjectIdentifier agreeAlgID = keyEncAlg.Algorithm;
  118. ICipherParameters senderPublicParams = senderPublicKey;
  119. ICipherParameters receiverPrivateParams = receiverPrivateKey;
  120. if (agreeAlgID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
  121. {
  122. byte[] ukmEncoding = info.UserKeyingMaterial.GetOctets();
  123. MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.GetInstance(
  124. Asn1Object.FromByteArray(ukmEncoding));
  125. AsymmetricKeyParameter ephemeralKey = GetPublicKeyFromOriginatorPublicKey(
  126. receiverPrivateKey, ukm.EphemeralPublicKey);
  127. senderPublicParams = new MqvPublicParameters(
  128. (ECPublicKeyParameters)senderPublicParams,
  129. (ECPublicKeyParameters)ephemeralKey);
  130. receiverPrivateParams = new MqvPrivateParameters(
  131. (ECPrivateKeyParameters)receiverPrivateParams,
  132. (ECPrivateKeyParameters)receiverPrivateParams);
  133. }
  134. IBasicAgreement agreement = AgreementUtilities.GetBasicAgreementWithKdf(
  135. agreeAlgID, wrapAlg);
  136. agreement.Init(receiverPrivateParams);
  137. BigInteger agreedValue = agreement.CalculateAgreement(senderPublicParams);
  138. int wrapKeySize = GeneratorUtilities.GetDefaultKeySize(wrapAlg) / 8;
  139. byte[] wrapKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, wrapKeySize);
  140. return ParameterUtilities.CreateKeyParameter(wrapAlg, wrapKeyBytes);
  141. }
  142. private KeyParameter UnwrapSessionKey(
  143. string wrapAlg,
  144. KeyParameter agreedKey)
  145. {
  146. byte[] encKeyOctets = encryptedKey.GetOctets();
  147. IWrapper keyCipher = WrapperUtilities.GetWrapper(wrapAlg);
  148. keyCipher.Init(false, agreedKey);
  149. byte[] sKeyBytes = keyCipher.Unwrap(encKeyOctets, 0, encKeyOctets.Length);
  150. return ParameterUtilities.CreateKeyParameter(GetContentAlgorithmName(), sKeyBytes);
  151. }
  152. internal KeyParameter GetSessionKey(
  153. AsymmetricKeyParameter receiverPrivateKey)
  154. {
  155. try
  156. {
  157. string wrapAlg = DerObjectIdentifier.GetInstance(
  158. Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]).Id;
  159. AsymmetricKeyParameter senderPublicKey = GetSenderPublicKey(
  160. receiverPrivateKey, info.Originator);
  161. KeyParameter agreedWrapKey = CalculateAgreedWrapKey(wrapAlg,
  162. senderPublicKey, receiverPrivateKey);
  163. return UnwrapSessionKey(wrapAlg, agreedWrapKey);
  164. }
  165. catch (SecurityUtilityException e)
  166. {
  167. throw new CmsException("couldn't create cipher.", e);
  168. }
  169. catch (InvalidKeyException e)
  170. {
  171. throw new CmsException("key invalid in message.", e);
  172. }
  173. catch (Exception e)
  174. {
  175. throw new CmsException("originator key invalid.", e);
  176. }
  177. }
  178. /**
  179. * decrypt the content and return an input stream.
  180. */
  181. public override CmsTypedStream GetContentStream(
  182. ICipherParameters key)
  183. {
  184. if (!(key is AsymmetricKeyParameter))
  185. throw new ArgumentException("KeyAgreement requires asymmetric key", "key");
  186. AsymmetricKeyParameter receiverPrivateKey = (AsymmetricKeyParameter) key;
  187. if (!receiverPrivateKey.IsPrivate)
  188. throw new ArgumentException("Expected private key", "key");
  189. KeyParameter sKey = GetSessionKey(receiverPrivateKey);
  190. return GetContentFromSessionKey(sKey);
  191. }
  192. }
  193. }
  194. #pragma warning restore
  195. #endif