Я не эксперт в шифровании, но я пытаюсь создать CMSEnvelopedDataGenerator с bouncycastle 1.67, где ключ сеанса зашифрован с помощью RSAES-OAEP (1.2.840.113549.1.1.7)
Пока мой код выглядит так:
CMSEnvelopedDataGenerator envelopedGenerator = new CMSEnvelopedDataGenerator();
JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
OAEPParameterSpec oaepSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
AlgorithmIdentifier algorithmIdentifier;
algorithmIdentifier = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepSpec);
JceKeyTransRecipientInfoGenerator recipent = new JceKeyTransRecipientInfoGenerator(receiverCert, algorithmIdentifier).setProvider("BC");
# encrypt
CMSEnvelopedData envelopedData;
envelopedData = envelopedGenerator.generate(
new CMSProcessableByteArray(encodedSignedData),
new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider("BC").build()
)
Он проходит, но когда я проверяю его через openssl asn1parse, я вижу
115:d=6 hl=2 l= 9 prim: OBJECT :rsaesOaep
126:d=6 hl=2 l= 47 cons: SEQUENCE
128:d=7 hl=2 l= 15 cons: cont [ 0 ]
130:d=8 hl=2 l= 13 cons: SEQUENCE
132:d=9 hl=2 l= 9 prim: OBJECT :sha256
143:d=9 hl=2 l= 0 prim: NULL
145:d=7 hl=2 l= 28 cons: cont [ 1 ]
147:d=8 hl=2 l= 26 cons: SEQUENCE
149:d=9 hl=2 l= 9 prim: OBJECT :mgf1
160:d=9 hl=2 l= 13 cons: SEQUENCE
162:d=10 hl=2 l= 9 prim: OBJECT :sha256
а затем шестнадцатеричный дамп. В моем справочном файле это выглядит так:
115:d=6 hl=2 l= 9 prim: OBJECT :rsaesOaep
126:d=6 hl=2 l= 43 cons: SEQUENCE
128:d=7 hl=2 l= 13 cons: cont [ 0 ]
130:d=8 hl=2 l= 11 cons: SEQUENCE
132:d=9 hl=2 l= 9 prim: OBJECT :sha256
143:d=7 hl=2 l= 26 cons: cont [ 1 ]
145:d=8 hl=2 l= 24 cons: SEQUENCE
147:d=9 hl=2 l= 9 prim: OBJECT :mgf1
158:d=9 hl=2 l= 11 cons: SEQUENCE
160:d=10 hl=2 l= 9 prim: OBJECT :sha256
В строке 143 в моем файле есть строка
143:d=9 hl=2 l= 0 prim: NULL
Я не уверен, откуда это взялось.
Когда я использую свой код расшифровки, который работает для моего справочного файла, я получаю следующие исключения
exception unwrapping key: bad padding: unable to decrypt block
Caused by: org.bouncycastle.cms.CMSException: exception unwrapping key: bad padding: unable to decrypt block
at org.bouncycastle.cms.jcajce.JceKeyTransRecipient.extractSecretKey(Unknown Source)
at org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.KeyTransRecipientInformation.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.RecipientInformation.getContentStream(Unknown Source)
Caused by: org.bouncycastle.operator.OperatorException: bad padding: unable to decrypt block
at org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper.generateUnwrappedKey(Unknown Source)
Caused by: org.bouncycastle.jcajce.provider.util.BadBlockException: unable to decrypt block
at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.getOutput(Unknown Source)
at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(Cipher.java:2168)
Caused by: org.bouncycastle.crypto.InvalidCipherTextException: data wrong
at org.bouncycastle.crypto.encodings.OAEPEncoding.decodeBlock(Unknown Source)
at org.bouncycastle.crypto.encodings.OAEPEncoding.processBlock(Unknown Source)
Я надеюсь, что это не так много, этого не хватает.
Редактировать:
С моим неправильно сгенерированным файлом recipient.getKeyEncryptionAlgorithm().getParameters() приводит к
[[0][2.16.840.1.101.3.4.2.1, NULL], [1][1.2.840.113549.1.1.8, [2.16.840.1.101.3.4.2.1, NULL]]]
правильный файл в
[[0][2.16.840.1.101.3.4.2.1], [1][1.2.840.113549.1.1.8, [2.16.840.1.101.3.4.2.1]]]
Откуда берутся эти неправильные NULL значения SHA-256.




Вы упоминаете только один «лишний» NULL в сообщении, созданном BC, но на самом деле их два, причем второй в первой строке вы исключили из опубликованных вами данных. Поля (разной) длины в вашем посте, а также отображение getParameters() ясно показывают это.
Эти NULL не являются неправильными.
Эти значения NULL являются параметрами алгоритмов хеширования в структуре параметров OAEP и требуются стандартом. Из RFC 3447 = PKCS1v2.1, которая является первой версией, включающей SHA-2 (в 2003 г., сразу после FIPS 186-2 в 2002 г.) в A.2.1:
The parameters field ... shall have a value of type RSAES-OAEP-params:
RSAES-OAEP-params ::= SEQUENCE {
hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
pSourceAlgorithm [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty
}
...
HashAlgorithm ::= AlgorithmIdentifier {
{OAEP-PSSDigestAlgorithms}
}
OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
{ OID id-sha1 PARAMETERS NULL }|
{ OID id-sha256 PARAMETERS NULL }|
{ OID id-sha384 PARAMETERS NULL }|
{ OID id-sha512 PARAMETERS NULL },
... -- Allows for future expansion --
}
...
MaskGenAlgorithm ::= AlgorithmIdentifier {
{PKCS1MGFAlgorithms}
}
PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
{ OID id-mgf1 PARAMETERS HashAlgorithm },
... -- Allows for future expansion --
}
Обратите внимание, что обе спецификации хэша — внешний хеш для метки и внутренний хеш в параметрах MGF1 — определяются информационным набором HashAlgorithm, и все определенные значения в этом наборе, включая SHA-256, имеют параметры, явно равные NULL, а не опущенные, поскольку общие разрешения X.509 ASN.1 (сравните RFC5280 4.1.1.2, в котором используется старая нотация pre-infoset).
Обратите внимание, что то же самое верно для PSS в A.2.3 и с немного большим набором алгоритмов хеширования для DigestInfo в RSASSA-PKCS1-v1_5 в A.2.4. Это и эквивалентные положения в версии 2.0 (за исключением PSS, которого не было в версии 2.0, и с немного другими обозначениями) могут быть реакцией на PKCS1v1.5 в 10.1.2, только делая параметры подписи DigestInfo «должными» (нижний регистр даже после 2119 года, предположительно потому, что это был текст RSALabs, а не IETF), что привело к различиям в реализациях, из-за которых подписи, которые на самом деле были правильными, иногда не проверялись, что считалось плохой вещью, нуждающейся в исправлении.
Таким образом, ваш «справочный» файл технически нарушает стандарт. Однако, поскольку эти хеш-алгоритмы на самом деле не используют параметры — вот почему они кодируются с помощью NULL — BouncyCastle может легко быть терпимым и принимать опущенный регистр. Я протестировал действующую в остальном структуру, и она работает в обоих направлениях. (Меня не удивит, если он будет работать даже с каким-то неподходящим значением, например, с вставленной туда строкой октетов, но я этого не проверял.)
Даже если кодировка параметров была неправильной, это не вызовет исключения, которое у вас есть - это будет либо явная ошибка декодирования/анализа, например, «отсутствует обязательное поле», либо ошибка создания экземпляра, например, «недопустимые параметры для алгоритма x». При отсутствии ошибок «плохое заполнение» вызвано поврежденными, подделанными или иным образом неправильными данными (что в среде CMS маловероятно) или несоответствием ключей.
Убедитесь, что вы используете совпадающие ключи.
Спасибо за подробный ответ. После дальнейшей отладки я обнаружил ошибку при расшифровке в сочетании с несколькими получателями.