Статус: Участник
Группы: Участники
Зарегистрирован: 18.12.2013(UTC) Сообщений: 27
Сказал(а) «Спасибо»: 14 раз
|
Получил на выходе заветный p7m, но на стороне получателя не могут его расшифровать. Думаю, что проблема, либо с моим шифрованием, либо с формированием cms-сообщения. Так как шифровать нужно на сертификате получателя, то шифрую так:
- Генерирую эфемерную ключевую пару
- Генерирую ключ согласования из эфемерного закрытого и сертификата получателя
- Создаю случайный секретный ключ
- Шифрую секретный ключ на ключе согласования
- Шифрую данные случайным секретным ключом
А дальше формирую CMS-сообщение как в CMSSignAndEncrypt из Samples/sample-sources/CMS_samples. Вот код моей функции шифрования и получения p7m, а также всех используемых в ней функций: Код:
public static final void DEREncoded2(String path,
java.security.cert.X509Certificate publicSenderCert,
java.security.cert.X509Certificate responderCert) throws IOException,
Asn1Exception, CertificateEncodingException, NoSuchAlgorithmException,
InvalidKeyException, SignatureException, InvalidAlgorithmParameterException,
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
/* Получил данные для шифрования */
byte[] buffer = Array.readFile(path);
/* Сгенерировал эфемерную пару ключей */
KeyPair ephemerialPair = generateKeyPair(CryptoProvider.GOST_EPH_DH_NAME);
/* Сгенерировал ключ согласования из эфемерного закрытого и сертификата получателя */
// sv = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }
SecretKey agreementKey = generateAgreementKey(ephemerialPair.getPrivate(), responderCert, sv);
/* Взял параметры из контрольной панели (по-умолчанию) */
ParamsInterface paramss = AlgIdSpec.getDefaultCryptParams();
/* Создал секретный ключ с параметрами из контрольной панели */
SecretKey randomSymmKey = generateSymmetricKey();
/* Зашифровал секретный ключ на ключе согласования */
byte[] key = encryptKey("GOST28147/CFB/NoPadding", randomSymmKey, agreementKey);
/* И, наконец, шифрую данные */
Cipher cip = Cipher.getInstance("GOST28147/CFB/NoPadding");
cip.init(Cipher.ENCRYPT_MODE, randomSymmKey, (SecureRandom) null);
byte[] iv = cip.getIV();
byte[] cipher = cip.doFinal(buffer, 0, buffer.length);
/* Формирование CMS-сообщения */
final ContentInfo all = new ContentInfo();
all.contentType
= new Asn1ObjectIdentifier(new OID(STR_CMS_OID_ENVELOPED).value);
final EnvelopedData cms = new EnvelopedData();
all.content = cms;
cms.version = new CMSVersion(0);
cms.recipientInfos = new RecipientInfos(1);
cms.recipientInfos.elements = new RecipientInfo[1];
cms.recipientInfos.elements[0] = new RecipientInfo();
final KeyTransRecipientInfo keytrans = new KeyTransRecipientInfo();
keytrans.version = new CMSVersion(0);
final Asn1BerEncodeBuffer ebuf = new Asn1BerEncodeBuffer();
final SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo();
final Asn1BerDecodeBuffer dbuff = new Asn1BerDecodeBuffer(
publicSenderCert.getPublicKey().getEncoded());
spki.decode(dbuff);
dbuff.reset();
final AlgIdInterface algid = new AlgIdSpec(spki.algorithm);
final AlgorithmIdentifier id = (AlgorithmIdentifier) algid.getDecoded();
id.encode(ebuf);
Asn1BerDecodeBuffer dbuf = new Asn1BerDecodeBuffer(ebuf.getMsgCopy());
keytrans.keyEncryptionAlgorithm = new KeyEncryptionAlgorithmIdentifier();
keytrans.keyEncryptionAlgorithm.decode(dbuf);
ebuf.reset();
dbuf.reset();
keytrans.rid = new RecipientIdentifier();
final IssuerAndSerialNumber issuer = new IssuerAndSerialNumber();
final X500Principal issuerName = responderCert.getIssuerX500Principal();
dbuf = new Asn1BerDecodeBuffer(issuerName.getEncoded());
issuer.issuer = new Name();
final RDNSequence rnd = new RDNSequence();
rnd.decode(dbuf);
issuer.issuer.set_rdnSequence(rnd);
issuer.serialNumber = new CertificateSerialNumber(
responderCert.getSerialNumber());
keytrans.rid.set_issuerAndSerialNumber(issuer);
dbuf.reset();
final GostR3410_KeyTransport encrKey = new GostR3410_KeyTransport();
dbuf = new Asn1BerDecodeBuffer(key);
encrKey.sessionEncryptedKey = new Gost28147_89_EncryptedKey();
encrKey.sessionEncryptedKey.decode(dbuf);
dbuf.reset();
encrKey.transportParameters = new GostR3410_TransportParameters();
encrKey.transportParameters.encryptionParamSet
= new Gost28147_89_ParamSet(algid.getCryptParams()
.getOID().value);
encrKey.transportParameters.ephemeralPublicKey = new SubjectPublicKeyInfo();
dbuf = new Asn1BerDecodeBuffer(
publicSenderCert.getPublicKey().getEncoded());
encrKey.transportParameters.ephemeralPublicKey.decode(dbuf);
dbuf.reset();
encrKey.transportParameters.ukm = new Asn1OctetString(sv);
encrKey.encode(ebuf);
keytrans.encryptedKey = new EncryptedKey(ebuf.getMsgCopy());
ebuf.reset();
cms.recipientInfos.elements[0].set_ktri(keytrans);
cms.encryptedContentInfo = new EncryptedContentInfo();
final OID contentType = new OID(STR_CMS_OID_DATA);
cms.encryptedContentInfo.contentType = new ContentType(contentType.value);
final Gost28147_89_Parameters params = new Gost28147_89_Parameters();
params.iv = new Gost28147_89_IV(iv);
params.encryptionParamSet
= new Gost28147_89_ParamSet(paramss.getOID().value);
cms.encryptedContentInfo.contentEncryptionAlgorithm
= new ContentEncryptionAlgorithmIdentifier(
_Gost28147_89_EncryptionSyntaxValues.id_Gost28147_89,
params);
cms.encryptedContentInfo.encryptedContent = new EncryptedContent(cipher);
all.encode(ebuf);
Array.writeFile(path + ".p7m", ebuf.getMsgCopy());
}
public static final SecretKey generateAgreementKey(Key senderKey,
Certificate responderCertificate, byte[] startVector)
throws NoSuchAlgorithmException, InvalidKeyException,
InvalidAlgorithmParameterException {
/* Ключ обмена, соответствующий закрытому ключу */
PublicKey publicKey = responderCertificate.getPublicKey();
/* создание генератора ключей согласования */
KeyAgreement senderKeyAgree = KeyAgreement.getInstance(JCP.GOST_DH_NAME);
/* Инициализация генератора ключей согласования */
senderKeyAgree.init(senderKey, new IvParameterSpec(startVector), null);
/* Фаза согласования открытого и закрытого ключей */
senderKeyAgree.doPhase(publicKey, true);
/* Генерация ключа согласования */
return senderKeyAgree.generateSecret(CryptoProvider.GOST_CIPHER_NAME);
}
public static final SecretKey generateSymmetricKey(ParamsInterface... params)
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
/* Создание генератора симметричных ключей шифрования */
KeyGenerator kg = KeyGenerator.getInstance(CryptoProvider.GOST_CIPHER_NAME);
/* Установка параметров шифрования */
kg.init(params.length == 0 ? AlgIdSpec.getDefaultCryptParams() : params[0]);
/* Генерация симметричного ключа шифрования */
return kg.generateKey();
}
public static final byte[] encryptKey(String cipherMode, SecretKey toEncrypt,
SecretKey byEncrypt) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException {
/* Получение экземпляра шифратора */
Cipher cipher = Cipher.getInstance(cipherMode);
/* Инициализация шифратора в режиме шифрования ключей */
cipher.init(Cipher.WRAP_MODE, toEncrypt, (SecureRandom) null);
/* Шифрование ключа */
return cipher.wrap(byEncrypt);
}
public static final KeyPair generateKeyPair(String algorithm)
throws NoSuchAlgorithmException {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm);
return keyGen.generateKeyPair();
}
Подскажите пожалуйста по правильному ли алгоритму я шифрую данные или шифрование на сертификате выполняется как-либо по-другому? Согласно какому RFC формируются p7m-файлы и обоснованно ли считать, что это те же CMS как в RFC 5652? Конечно, был бы очень признателен, если бы вы указали на ошибки в коде, но особо на это не надеюсь.
|