Статус: Активный участник
Группы: Участники
Зарегистрирован: 16.02.2016(UTC) Сообщений: 60
Сказал(а) «Спасибо»: 18 раз Поблагодарили: 2 раз в 2 постах
|
Цель залить на сервис партнеру зашифрованный подписанный файл. Используя примеры из samples.jar получаю ошибку от сервиса. По доке ошибка значит "Допустимо только шифрование PKCS#7" Метод подписи: Код:.
fun sign(data: ByteArray, key: PrivateKey, cert: Certificate): ByteArray {
val certStore: Store = JcaCertStore(setOf(cert))
val generator = CMSSignedDataGenerator()
val contentSigner: ContentSigner = GostContentSignerProvider(
key, JCP.PROVIDER_NAME
)
val signerInfoGenerator: SignerInfoGenerator =
JcaSignerInfoGeneratorBuilder(
GostDigestCalculatorProvider(key, JCP.PROVIDER_NAME)
).build(contentSigner, cert as X509Certificate)
generator.addSignerInfoGenerator(signerInfoGenerator)
generator.addCertificates(certStore)
val content: CMSProcessable = CMSProcessableByteArray(data)
val signedData =
generator.generate(content as CMSTypedData, true)
return signedData.encoded
}
Метод шифрования взял из примера CMS_samples/PKCS7EnvEphTransport: Код:fun encryptPkcs7(data: ByteArray, responderCert: X509Certificate): ByteArray {
val STR_CMS_OID_DATA = "1.2.840.113549.1.7.1"
val STR_CMS_OID_ENVELOPED = "1.2.840.113549.1.7.3"
// Параметры шифрования симметричного ключа (по умолчанию)
// и параметры шифрования данных (по умолчанию).
val algIdSpec = getAlgIdSpec(responderCert)
val recipientTransportParameters = algIdSpec.cryptParams // из открытого ключа
val contentEncryptionParameters = algIdSpec.cryptParams // могут быть другие
val CIPHER_MODE = "GOST28147/CFB/NoPadding"
// Генерирование симметричного ключа с параметрами
// шифрования из контрольной панели.
val kg = KeyGenerator.getInstance(
"GOST28147", "Crypto")
// Инициализация генератора.
kg.init(contentEncryptionParameters)
// Симметричный ключ.
val symmetricKey: SecretKey = kg.generateKey()
// Зашифрование текста на симметричном ключе.
val cipher = Cipher.getInstance(CIPHER_MODE, "Crypto")
cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, null as SecureRandom?)
val iv = cipher.iv
val text = cipher.doFinal(data, 0, data.size)
// Зашифрование симметричного ключа.
val keyTransport = wrap(symmetricKey, responderCert.publicKey,
recipientTransportParameters)
// Формирование CMS-сообщения.
val all = ContentInfo()
all.contentType = Asn1ObjectIdentifier(OID(STR_CMS_OID_ENVELOPED).value)
val cms = EnvelopedData()
all.content = cms
cms.version = CMSVersion(0)
cms.recipientInfos = RecipientInfos(1)
cms.recipientInfos.elements = arrayOfNulls(1)
cms.recipientInfos.elements[0] = RecipientInfo()
val key_trans = KeyTransRecipientInfo()
key_trans.version = CMSVersion(0)
val ebuf = Asn1BerEncodeBuffer()
val id = algIdSpec.decoded as AlgorithmIdentifier
id.encode(ebuf)
var dbuf = Asn1BerDecodeBuffer(ebuf.msgCopy)
key_trans.keyEncryptionAlgorithm = KeyEncryptionAlgorithmIdentifier()
key_trans.keyEncryptionAlgorithm.decode(dbuf)
ebuf.reset()
dbuf.reset()
key_trans.rid = RecipientIdentifier()
val issuer = IssuerAndSerialNumber()
val issuerName: X500Principal = responderCert.getIssuerX500Principal()
dbuf = Asn1BerDecodeBuffer(issuerName.encoded)
issuer.issuer = Name()
val rnd = RDNSequence()
rnd.decode(dbuf)
issuer.issuer.set_rdnSequence(rnd)
issuer.serialNumber = CertificateSerialNumber(responderCert.getSerialNumber())
key_trans.rid.set_issuerAndSerialNumber(issuer)
dbuf.reset()
key_trans.encryptedKey = EncryptedKey(keyTransport)
ebuf.reset()
cms.recipientInfos.elements[0].set_ktri(key_trans)
cms.encryptedContentInfo = EncryptedContentInfo()
val contentType = OID(STR_CMS_OID_DATA)
cms.encryptedContentInfo.contentType = ContentType(contentType.value)
val parameters = Gost28147_89_Parameters()
parameters.iv = Gost28147_89_IV(iv)
parameters.encryptionParamSet = Gost28147_89_ParamSet(contentEncryptionParameters.oid.value) // параметры шифрования данных
cms.encryptedContentInfo.contentEncryptionAlgorithm = ContentEncryptionAlgorithmIdentifier(
_Gost28147_89_EncryptionSyntaxValues.id_Gost28147_89, parameters)
cms.encryptedContentInfo.encryptedContent = EncryptedContent(text)
all.encode(ebuf)
return ebuf.msgCopy
}
@Throws(java.lang.Exception::class)
fun wrap(secretKey: SecretKey, recipientKey: PublicKey, recipientTransportParameters: ParamsInterface): ByteArray? {
// Определение алгоритма эфемерного ключа.
val ephKeyAlgorithm = JCP.GOST_EPH_DH_2012_256_NAME
// Генерация эфемерной пары.
val kgp = KeyPairGenerator.getInstance(
ephKeyAlgorithm)
// Устанавливаем нужные параметры, как у
// получателя.
val spec: AlgorithmParameterSpec = X509PublicKeySpec(recipientKey.encoded)
kgp.initialize(spec)
// Генерируем эфемерную пару. Ключи получат
// параметры recipientKey, а у него параметры
// - recipientTransportParameters.
val ephPair = kgp.generateKeyPair()
val privateKey = ephPair.private
val publicKey = ephPair.public
val syncro = ByteArray(8)
val random = SecureRandom.getInstance(JCP.CP_RANDOM)
random.nextBytes(syncro)
val iv = IvParameterSpec(syncro)
// Выработка ключа согласования.
val ka = KeyAgreement.getInstance(privateKey.algorithm)
ka.init(privateKey, iv)
ka.doPhase(recipientKey, true)
val dh: Key = ka.generateSecret("GOST28147") // dh получит параметры из privateKey, т.е. recipientTransportParameters
// Зашифрование симметричного ключа на ключе согласования
// отправителя. Передаются параметры шифрования ключа, если
// отличаются от тех, что у dh.
val cipher = Cipher.getInstance("GOST28147/CFB/NoPadding")
cipher.init(Cipher.WRAP_MODE, dh, recipientTransportParameters, null as SecureRandom?)
val wrappedKey = cipher.wrap(secretKey)
// Упаковка параметров и ключа.
val encryptedKey = Gost28147_89_EncryptedKey()
var decoder: Asn1BerDecodeBuffer? = Asn1BerDecodeBuffer(wrappedKey)
encryptedKey.decode(decoder)
val imita = encryptedKey.macKey.value
val wrapperKeyBytes = encryptedKey.encryptedKey.value
// Кодирование открытого ключа в SubjectPublicKeyInfo.
val publicKeyBytes = publicKey.encoded
val publicKeyInfo = SubjectPublicKeyInfo()
decoder = Asn1BerDecodeBuffer(publicKeyBytes)
publicKeyInfo.decode(decoder)
// Кодирование GostR3410_KeyTransport.
val keyTransport = GostR3410_KeyTransport()
val encoder = Asn1BerEncodeBuffer()
keyTransport.sessionEncryptedKey = Gost28147_89_EncryptedKey(wrapperKeyBytes, imita)
keyTransport.transportParameters = GostR3410_TransportParameters(
Gost28147_89_ParamSet(recipientTransportParameters.oid.value), // параметры шифрования ключа
publicKeyInfo,
Asn1OctetString(iv.iv))
keyTransport.encode(encoder)
return encoder.msgCopy
}
Полученный пример расшифровывается успешно самим JCP и так же через КриптоАРМ. Но сервис все равно дает ту ошибку. Можно конечно обратиться в ТП сервиса и попросить разъяснить ситуацию, но вот проблема, стандартный контейнер (подписать+зашифровать) собранный в КриптоАРМ успешно потребляется сервисом. То есть у меня не получается воспроизвести через JCP тоже самое. Отсюда вопрос правильный ли я код использую для требований сервиса ? Как можно точно провалидировать полученное pcks7 сообщение? Можно ли использовать пример enveloped + sign из cades пакета примеров ?
|