KeyAgreeRecipientInfoGenerator.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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.X509;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  12. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  13. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  14. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  15. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  16. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
  17. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
  18. {
  19. internal class KeyAgreeRecipientInfoGenerator : RecipientInfoGenerator
  20. {
  21. private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
  22. private DerObjectIdentifier keyAgreementOID;
  23. private DerObjectIdentifier keyEncryptionOID;
  24. private IList recipientCerts;
  25. private AsymmetricCipherKeyPair senderKeyPair;
  26. internal KeyAgreeRecipientInfoGenerator()
  27. {
  28. }
  29. internal DerObjectIdentifier KeyAgreementOID
  30. {
  31. set { this.keyAgreementOID = value; }
  32. }
  33. internal DerObjectIdentifier KeyEncryptionOID
  34. {
  35. set { this.keyEncryptionOID = value; }
  36. }
  37. internal ICollection RecipientCerts
  38. {
  39. set { this.recipientCerts = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(value); }
  40. }
  41. internal AsymmetricCipherKeyPair SenderKeyPair
  42. {
  43. set { this.senderKeyPair = value; }
  44. }
  45. public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
  46. {
  47. byte[] keyBytes = contentEncryptionKey.GetKey();
  48. AsymmetricKeyParameter senderPublicKey = senderKeyPair.Public;
  49. ICipherParameters senderPrivateParams = senderKeyPair.Private;
  50. OriginatorIdentifierOrKey originator;
  51. try
  52. {
  53. originator = new OriginatorIdentifierOrKey(
  54. CreateOriginatorPublicKey(senderPublicKey));
  55. }
  56. catch (IOException e)
  57. {
  58. throw new InvalidKeyException("cannot extract originator public key: " + e);
  59. }
  60. Asn1OctetString ukm = null;
  61. if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
  62. {
  63. try
  64. {
  65. IAsymmetricCipherKeyPairGenerator ephemKPG =
  66. GeneratorUtilities.GetKeyPairGenerator(keyAgreementOID);
  67. ephemKPG.Init(
  68. ((ECPublicKeyParameters)senderPublicKey).CreateKeyGenerationParameters(random));
  69. AsymmetricCipherKeyPair ephemKP = ephemKPG.GenerateKeyPair();
  70. ukm = new DerOctetString(
  71. new MQVuserKeyingMaterial(
  72. CreateOriginatorPublicKey(ephemKP.Public), null));
  73. senderPrivateParams = new MqvPrivateParameters(
  74. (ECPrivateKeyParameters)senderPrivateParams,
  75. (ECPrivateKeyParameters)ephemKP.Private,
  76. (ECPublicKeyParameters)ephemKP.Public);
  77. }
  78. catch (IOException e)
  79. {
  80. throw new InvalidKeyException("cannot extract MQV ephemeral public key: " + e);
  81. }
  82. catch (SecurityUtilityException e)
  83. {
  84. throw new InvalidKeyException("cannot determine MQV ephemeral key pair parameters from public key: " + e);
  85. }
  86. }
  87. DerSequence paramSeq = new DerSequence(
  88. keyEncryptionOID,
  89. DerNull.Instance);
  90. AlgorithmIdentifier keyEncAlg = new AlgorithmIdentifier(keyAgreementOID, paramSeq);
  91. Asn1EncodableVector recipientEncryptedKeys = new Asn1EncodableVector();
  92. foreach (X509Certificate recipientCert in recipientCerts)
  93. {
  94. TbsCertificateStructure tbsCert;
  95. try
  96. {
  97. tbsCert = TbsCertificateStructure.GetInstance(
  98. Asn1Object.FromByteArray(recipientCert.GetTbsCertificate()));
  99. }
  100. catch (Exception)
  101. {
  102. throw new ArgumentException("can't extract TBS structure from certificate");
  103. }
  104. // TODO Should there be a SubjectKeyIdentifier-based alternative?
  105. IssuerAndSerialNumber issuerSerial = new IssuerAndSerialNumber(
  106. tbsCert.Issuer, tbsCert.SerialNumber.Value);
  107. KeyAgreeRecipientIdentifier karid = new KeyAgreeRecipientIdentifier(issuerSerial);
  108. ICipherParameters recipientPublicParams = recipientCert.GetPublicKey();
  109. if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
  110. {
  111. recipientPublicParams = new MqvPublicParameters(
  112. (ECPublicKeyParameters)recipientPublicParams,
  113. (ECPublicKeyParameters)recipientPublicParams);
  114. }
  115. // Use key agreement to choose a wrap key for this recipient
  116. IBasicAgreement keyAgreement = AgreementUtilities.GetBasicAgreementWithKdf(
  117. keyAgreementOID, keyEncryptionOID.Id);
  118. keyAgreement.Init(new ParametersWithRandom(senderPrivateParams, random));
  119. BigInteger agreedValue = keyAgreement.CalculateAgreement(recipientPublicParams);
  120. int keyEncryptionKeySize = GeneratorUtilities.GetDefaultKeySize(keyEncryptionOID) / 8;
  121. byte[] keyEncryptionKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, keyEncryptionKeySize);
  122. KeyParameter keyEncryptionKey = ParameterUtilities.CreateKeyParameter(
  123. keyEncryptionOID, keyEncryptionKeyBytes);
  124. // Wrap the content encryption key with the agreement key
  125. IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionOID.Id);
  126. keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random));
  127. byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length);
  128. Asn1OctetString encryptedKey = new DerOctetString(encryptedKeyBytes);
  129. recipientEncryptedKeys.Add(new RecipientEncryptedKey(karid, encryptedKey));
  130. }
  131. return new RecipientInfo(new KeyAgreeRecipientInfo(originator, ukm, keyEncAlg,
  132. new DerSequence(recipientEncryptedKeys)));
  133. }
  134. private static OriginatorPublicKey CreateOriginatorPublicKey(
  135. AsymmetricKeyParameter publicKey)
  136. {
  137. SubjectPublicKeyInfo spki = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
  138. return new OriginatorPublicKey(
  139. new AlgorithmIdentifier(spki.AlgorithmID.Algorithm, DerNull.Instance),
  140. spki.PublicKeyData.GetBytes());
  141. }
  142. }
  143. }
  144. #pragma warning restore
  145. #endif