Я застрял в правильном создании запроса на подпись сертификата PKCS # 10 и печати HMAC. Мне нужно их создать и отправить на удаленный сервис, который выдаст мне сертификат в формате PKCS#7. Точнее:
Create a key pair for certificate and generate PKCS#10 request
(private key is never sent to the remote service)
use: key length 1024bit, SHA-1 algorithm, DER –encoded
Subject info: CN=name, serialNumber=userID, C=country (as above)
Create HMAC seal
use DER coded PKCS#10 above as input
SMS-activation code as the key (10-digits)
Я оборачиваю результат в SoapMessage и отправляю на удаленную службу и получаю ответ. Ответ — ошибка, потому что либо CSR, либо HMAC были сгенерированы неправильно. Удаленная служба не отправляет более конкретное сообщение об ошибке, но, как я уже сказал, ошибка связана с моим неправильно сгенерированным CSR или HMAC. Тема и ключ HMAC являются примерными значениями, предоставленными удаленной службой, поэтому проблема не может быть из-за них.
Вот код, как я его реализовал
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.SignatureException;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
public class CustomerCert {
private final KeyPairGenerator keyGen;
private final KeyPair keypair;
private final PublicKey publicKey;
private final PrivateKey privateKey;
private final byte[] pkcs10;
private HMac hmac;
private byte[] hmacBytes;
public CustomerCert(String company, String userId, String country)
throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException {
keyGen = KeyPairGenerator.getInstance("DSA");
keyGen.initialize(1024, new SecureRandom());
keypair = keyGen.generateKeyPair();
publicKey = keypair.getPublic();
privateKey = keypair.getPrivate();
pkcs10 = this.generatePKCS10(company, userId, country);
}
private byte[] generatePKCS10(String company, String userId, String country) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException {
String sigAlg = "SHA1withDSA";
String params = "CN=" + company + ", serialNumber=" + userId + ", C=" + country;
X500Principal principal = new X500Principal(params);
PKCS10CertificationRequest kpGen = new PKCS10CertificationRequest(sigAlg, principal, publicKey, new DERSet(), privateKey, null);
byte[] c = kpGen.getEncoded();
return c;
}
public String getCSRasString() throws UnsupportedEncodingException {
return new String(pkcs10, "ASCII"); // ISO-8859-1
}
public byte[] createHMacSeal(byte[] message, String key) throws UnsupportedEncodingException
{
hmac = new HMac(new SHA1Digest());
hmacBytes = new byte[hmac.getMacSize()];
{
hmac.init(new KeyParameter(Hex.decode(key)));
hmac.update(message, 0, message.length);
hmac.doFinal(hmacBytes, 0);
}
return hmacBytes;
}
}
В чем я не уверен, так это в том, как в соответствии с требованием сделать запрос PKCS кодированным DER?
Другой вопрос заключается в том, как дать hmac seal ввод pkcs в кодировке DER? И, наконец, как получить массив байтов сгенерированной печати HMAC, потому что удаленная служба требует его в виде массива байтов в кодировке base64?
ИЗМЕНИТЬ
Как указал @Jcs, мое создание PKCS правильное, но сейчас я не уверен в правильном создании HMAC. Теперь я получил лучший ответ от удаленного сервера, и теперь я получаю сообщение об ошибке error in MAC value
. Мои текущие методы создания HMac следующие:
public byte[] createHMacSeal(byte[] message, String key) {
String messageString = new String(message, "US-ASCII");
HMac hmac = new HMac(new SHA1Digest());
byte[] resBuf = new byte[hmac.getMacSize()];
{
byte[] m = messageString.getBytes();
if (messageString.startsWith("0x"))
{
m = Hex.decode(messageString.substring(2));
}
hmac.init(new KeyParameter(key.getBytes("US-ASCII")));
hmac.update(m, 0, m.length);
hmac.doFinal(resBuf, 0);
hmacBytes = resBuf;
}
return hmacBytes;
public byte[] createHMacSeal(byte[] message, String key) {
SecretKey secretKey = new SecretKeySpec(key.getBytes("US-ASCII"), "HMac-SHA1");
Mac mac;
mac = Mac.getInstance("HMac-SHA1", "BC");
mac.init(secretKey);
mac.reset();
mac.update(message, 0, message.length);
hmacBytes = mac.doFinal();
return hmacBytes;
}
Эти два метода возвращают разные значения для HMAC. Для аргументов метода byte[] message
— это PKCS getPKCS10()
в кодировке DER, а второй аргумент key
— это код активации SMS в виде строки из 10 символов 1234567890
. Теперь я действительно поражен и пробовал много разных возможностей, но все равно то же сообщение об ошибке с удаленного сервера.
DER coded PKCS#10
. Это весьkpGen.getEncoded()
или только открытый ключ от него? Потому что в спецификации сказано, что никогда не отправляйте закрытый ключ на удаленный сервер. Еще один вопрос по поводу печати HMAC – это ключ, который является кодом SMS-активации. Это правильный способ передать его в hmac как ключевой параметр, расшифрованный в шестнадцатеричном формате? И, наконец, из-за неясного определения, какой алгоритм для PKCS - RSA или DSA? - person Skyzer   schedule 14.11.2013