KeyAgreeRecipientInformation.cs 8.7 KB

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