문제

탄력성 성을 사용하지 않고 Java 코드로 X509 인증서를 SALELLY로 만들 수 있습니까? X509V*CertificateGenerator 클래스?

도움이 되었습니까?

해결책

인증서에 서명하는 기능은 표준 Java 라이브러리 또는 확장의 일부가 아닙니다.

직접 수행하는 데 필요한 많은 코드가 핵심의 일부입니다. X.500 이름, X.509 인증서 확장, 다양한 알고리즘에 대한 공개 키, 그리고 실제로 디지털 서명을 수행 할 수있는 클래스가 있습니다.

이것을 직접 구현하는 것은 사소한 일이 아니지만 확실히 가능합니다. 아마도 인증서 서명을 위해 처음으로 작업 프로토 타입을 만들었을 때 4 ~ 5 일을 보냈을 것입니다. 그것은 환상적입니다 나를 위해 운동을 배우지 만 무료로 사용할 수있는 라이브러리가있을 때 그 비용을 정당화하기는 어렵습니다.

다른 팁

예, 그러나 공개적으로 문서화 된 수업은 아닙니다. 나는 그 과정을 문서화했다 이 기사에서.

import sun.security.x509.*;
import java.security.cert.*;
import java.security.*;
import java.math.BigInteger;
import java.util.Date;
import java.io.IOException

/** 
 * Create a self-signed X.509 Certificate
 * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
 * @param pair the KeyPair
 * @param days how many days from now the Certificate is valid for
 * @param algorithm the signing algorithm, eg "SHA1withRSA"
 */ 
X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
  throws GeneralSecurityException, IOException
{
  PrivateKey privkey = pair.getPrivate();
  X509CertInfo info = new X509CertInfo();
  Date from = new Date();
  Date to = new Date(from.getTime() + days * 86400000l);
  CertificateValidity interval = new CertificateValidity(from, to);
  BigInteger sn = new BigInteger(64, new SecureRandom());
  X500Name owner = new X500Name(dn);
 
  info.set(X509CertInfo.VALIDITY, interval);
  info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
  info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
  info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
  info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
  info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
  AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
  info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
 
  // Sign the cert to identify the algorithm that's used.
  X509CertImpl cert = new X509CertImpl(info);
  cert.sign(privkey, algorithm);
 
  // Update the algorith, and resign.
  algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
  info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
  cert = new X509CertImpl(info);
  cert.sign(privkey, algorithm);
  return cert;
}   
import sun.security.x509.*;

import java.security.cert.*;
import java.security.*;
import java.math.BigInteger;
import java.security.cert.Certificate;
import java.util.Date;
import java.io.IOException;

public class Example {
    /**
     * Create a self-signed X.509 Example
     *
     * @param dn        the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
     * @param pair      the KeyPair
     * @param days      how many days from now the Example is valid for
     * @param algorithm the signing algorithm, eg "SHA1withRSA"
     */
    public X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
            throws GeneralSecurityException, IOException {
        PrivateKey privkey = pair.getPrivate();
        X509CertInfo info = new X509CertInfo();
        Date from = new Date();
        Date to = new Date(from.getTime() + days * 86400000l);
        CertificateValidity interval = new CertificateValidity(from, to);
        BigInteger sn = new BigInteger(64, new SecureRandom());
        X500Name owner = new X500Name(dn);

        info.set(X509CertInfo.VALIDITY, interval);
        info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
        info.set(X509CertInfo.SUBJECT, owner);
        info.set(X509CertInfo.ISSUER, owner);
        info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
        info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
        AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
        info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));

        // Sign the cert to identify the algorithm that's used.
        X509CertImpl cert = new X509CertImpl(info);
        cert.sign(privkey, algorithm);

        // Update the algorith, and resign.
        algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG);
        info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
        cert = new X509CertImpl(info);
        cert.sign(privkey, algorithm);
        return cert;
    }

    public static void main (String[] argv) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        Example example = new Example();
        String distinguishedName = "CN=Test, L=London, C=GB";
        Certificate certificate = example.generateCertificateOriginal(distinguishedName, keyPair, 365, "SHA256withRSA");
        System.out.println("it worked!");
    }
}

나는 Vbence의 대답을 좋아했지만 다음과 같은 예외를 계속 얻었습니다.

java.security.cert.certificateException : 주제 클래스 유형이 잘못되었습니다.

많은 시도를 한 후에 ~였다 유효한 주제 클래스는 x509cerinfo가 x500name 인스턴스를 원한다는 것을 알았습니다.

1 info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
2 info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
3 info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
4 info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));

따라서 2와 3 행은 변경해야했습니다

2 info.set(X509CertInfo.SUBJECT, owner);
3 info.set(X509CertInfo.ISSUER, owner);

자체 서명 된 인증서 (서명, x509 인코딩 등)를 만들기위한 모든 기본 구성 요소는 JRE에서 제공됩니다. BC와 달리 Sun의 JCE는 인증서에 서명하기위한 공개 전화를 제공하지 않습니다. 그러나 모든 기능은 KeyTool에서 제공됩니다. KeyTool에서 코드를 복사하여이를 수행 할 수 있습니다. 복사 해야하는 방법은 다음과 같습니다 doSelfCert().

정확히 무엇을하고 싶은지 (그리고 아마도 "sanely"에 대한 당신의 정의)에 따라 다릅니다. ZZ Coder가 지적했듯이 복사하여 자체 서명 된 인증서를 직접 만들 수 있습니다. KeyTool. 그러나 표준 JCE를 사용하여 PKCS10 인증서 요청 객체를 만들 수 있다고 생각하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top