KeyAgreeRecipientInfoGenerator.cs 5.9 KB

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