나는 살아야 할 이상한 요구 사항이 있습니다. 암호화 시스템에 TBS 인증서를 전달해야합니다. 서명 한 인증서의 문자열을 서명 된 인증서를 만들기 위해 인증서에 통합해야합니다.인증서에 서명 추가
SO.COM에서 com.ibm.security.x509.X509CertImpl 및 다양한 BouncyCastle 게시물을 보면 어떻게 수행 할 수 없는지 알 수 있습니다.
질문 :
이 가능합니까? 그렇다면 어떻게?
나는 살아야 할 이상한 요구 사항이 있습니다. 암호화 시스템에 TBS 인증서를 전달해야합니다. 서명 한 인증서의 문자열을 서명 된 인증서를 만들기 위해 인증서에 통합해야합니다.인증서에 서명 추가
SO.COM에서 com.ibm.security.x509.X509CertImpl 및 다양한 BouncyCastle 게시물을 보면 어떻게 수행 할 수 없는지 알 수 있습니다.
질문 :
이 가능합니까? 그렇다면 어떻게?
BouncyCastle X509v3CertificateBuilder 클래스 (pkix jar)의 소스 코드를 참조하고 필요에 맞게 조정할 수 있습니다. 이 클래스는 V3TBSCertificateGenerator를 사용하여 TBSCertificate을 생성합니다. 이것은 DER로 인코딩 할 수있는 ASN.1 객체입니다. 그런 다음 "암호화 시스템"에 의해 서명 된 DER 인코딩을 얻을 수 있습니다. 그런 다음 TBS 인증서와 서명을 최종 X.509 인증서에 넣는 방법에 관해서는 X509v3CertificateBuilder.build() 메서드를 참조하십시오.
저는 한 가지 방법을 보여주는 예제를 작성했습니다. 이 코드의 대부분은 bouncycastle pkix 또는 lwcrypto 라이브러리에서 도난 당했지만 모든 버그는 거의 확실합니다. 아래에 집중하는 가장 중요한 방법은 generateCert
입니다. 나머지 코드는 테스트를 수행하는 테스트 장치입니다.
이 코드는 특별히 bounycastle bcpkix 및 lwcrypto jars 만 필요로 작성되었습니다. lwcrypto 대신 bcprov jar를 사용하면 다소 단축 될 수 있습니다.
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.TBSCertificate;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.bc.BcX509v3CertificateBuilder;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import javax.security.auth.x500.X500Principal;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Date;
public class Main {
private static class TBSCertPlusSignature {
private final byte[] encodedTbsCert;
private final byte[] signature;
public TBSCertPlusSignature(byte[] encodedTbsCert, byte[] signature) {
this.encodedTbsCert = encodedTbsCert;
this.signature = signature;
}
public byte[] getEncodedTbsCert() {
return encodedTbsCert;
}
public byte[] getSignature() {
return signature;
}
}
private static TBSCertPlusSignature makeTestCert(KeyPair keyPair) throws Exception {
Date now = new Date();
Date nowPlus1Hour = new Date(now.getTime() + 1000 * 60 * 60 * 1L);
byte[] encodedName = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").getEncoded();
X500Name issuer = X500Name.getInstance(encodedName);
X500Name subject = issuer;
RSAPublicKey rsaPub = (RSAPublicKey) keyPair.getPublic();
RSAKeyParameters rsaPubParams = new RSAKeyParameters(false, rsaPub.getModulus(), rsaPub.getPublicExponent());
BcX509v3CertificateBuilder certBuilder = new BcX509v3CertificateBuilder(
issuer,
BigInteger.valueOf(100L),
now,
nowPlus1Hour,
subject,
rsaPubParams
);
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSA");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) keyPair.getPrivate();
RSAPrivateCrtKeyParameters rsaPrivParams = new RSAPrivateCrtKeyParameters(
rsaPriv.getModulus(),
rsaPriv.getPublicExponent(),
rsaPriv.getPrivateExponent(),
rsaPriv.getPrimeP(),
rsaPriv.getPrimeQ(),
rsaPriv.getPrimeExponentP(),
rsaPriv.getPrimeExponentQ(),
rsaPriv.getCrtCoefficient()
);
ContentSigner contentSigner = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(rsaPrivParams);
final X509CertificateHolder x509CertificateHolder = certBuilder.build(contentSigner);
byte[] tbsCertDER = x509CertificateHolder.toASN1Structure().getTBSCertificate().getEncoded();
byte[] signature = x509CertificateHolder.getSignature();
return new TBSCertPlusSignature(tbsCertDER, signature);
}
private static X509Certificate generateCert(byte[] tbsCertEncoded, byte[] signature) throws Exception {
// Given the der encoded TBS cert and signature, create the corresponding X509 certificate
TBSCertificate tbsCert = TBSCertificate.getInstance(tbsCertEncoded);
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(tbsCert);
v.add(tbsCert.getSignature());
v.add(new DERBitString(signature));
DERSequence derSequence = new DERSequence(v);
ByteArrayInputStream baos = new ByteArrayInputStream(derSequence.getEncoded());
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(baos);
}
public static void main(String[] args) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.generateKeyPair();
TBSCertPlusSignature testData = makeTestCert(keyPair);
X509Certificate x509Cert = generateCert(testData.getEncodedTbsCert(), testData.getSignature());
// Verify the signature
x509Cert.verify(keyPair.getPublic());
// Print the cert
PublicKey publicKey = x509Cert.getPublicKey();
System.out.println(x509Cert);
}
}