java - 如何生成要作为参数发送给 KeyStore.PrivateKeyEntry 的证书链?

标签 java cryptography certificate rsa keystore

我是 Java 编程的初学者。我的代码加密从文本文件中提取的数据,并使用 RSA 算法将其存储在另一个文件中。我想通过使用 KeyStore 类 (http://download.oracle.com/javase/1,5.0/docs/api/java/security/KeyStore.html) 及其嵌套类 - KeyStore 来保护我的私钥密码。 PrivateKeyEntry (http://download.oracle.com/javase/1,5.0/docs/api/java/security/KeyStore.PrivateKeyEntry.html)。

KeyStore.PrivateKeyEntry 的构造函数需要一个 Certificate[] 数组,我不确定如何生成这个 Certificate[] 数组。

到目前为止,我附上了我的代码和问题:

这是加密代码。

public class Fileencrypt {

     public static void main(String args[])  throws IOException, InvalidKeyException, java.security.InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, KeyStoreException, CertificateException, CertificateEncodingException, IllegalStateException, NoSuchProviderException, SignatureException, UnrecoverableKeyException{   
     try{ 

         byte[] plainData;
         byte[] encryptedData = null;

         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
         kpg.initialize(2048);
         KeyPair kp = kpg.genKeyPair();
         PublicKey publicKey = kp.getPublic();
         PrivateKey privateKey = kp.getPrivate();



         Cipher cipher = Cipher.getInstance("RSA");
         cipher.init(Cipher.ENCRYPT_MODE, publicKey);

         try { 
         X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
        FileOutputStream fos = new FileOutputStream("C:\\Output\\Publickey.txt");
        fos.write(x509EncodedKeySpec.getEncoded());
        fos.close();
        // Store Private Key.
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
        fos = new FileOutputStream("C:\\Output\\Privatekey.txt");
        fos.write(pkcs8EncodedKeySpec.getEncoded());
        fos.close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }





         File f = new File("C:\\Output\\text.txt");
         FileInputStream in = new FileInputStream(f);
         plainData = new byte[(int)f.length()];
         in.read(plainData);

         try {
            encryptedData = cipher.doFinal(plainData);
        } catch (IllegalBlockSizeException e) {

            e.printStackTrace();
        } catch (BadPaddingException e) {

            e.printStackTrace();
        }

        System.out.println(encryptedData); 
        FileOutputStream target = new FileOutputStream(new File("C:\\Output\\encrypted.txt"));
         target.write(encryptedData);
         target.close();   
     }   
     catch(IOException e){e.printStackTrace();}   
     catch(InvalidKeyException ei){ei.printStackTrace();
     }   
     }   
   }

这是解密代码。

public class Filedecrypt {

public static void main(String args[]) throws IOException,
        InvalidKeyException, java.security.InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException,
        BadPaddingException {
    try {

        byte[] plainData = null;
        byte[] encryptedData;
        File f1 = new File("C:\\Output\\Privatekey.txt");
        FileInputStream in1 = new FileInputStream(f1);
        byte[] bytekey = new byte[(int) f1.length()];
        in1.read(bytekey);
        KeyFactory keyFac = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytekey);

        PrivateKey key = keyFac.generatePrivate(keySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, key);

        File f = new File("C:\\Output\\encrypted.txt");
        FileInputStream in = new FileInputStream(f);
        encryptedData = new byte[(int) f.length()];
        in.read(encryptedData);

        try {
            plainData = cipher.doFinal(encryptedData);
        } catch (IllegalBlockSizeException e) {

            e.printStackTrace();
        } catch (BadPaddingException e) {

            e.printStackTrace();
        }

        FileOutputStream target = new FileOutputStream(
                new File(
                        "C:\\Output\\text1.txt"));
        target.write(plainData);
        target.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InvalidKeyException ei) {
        ei.printStackTrace();
    } catch (InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

最佳答案

如果你想用证书保存私钥,你可以使用这样的东西:

/**
 * Create new Certificate Authority.
 * @param keyAlgorithm key algorithm
 * @param keyLength key length
 * @param storePassword store password
 * @param keyPassword private key password
 * @param alias alias in key store
 * @param signatureAlgorithm signature algorithm
 * @param issuer issuer
 * @param validFrom certificate validity first date
 * @param validTo certificate validity last date
 * @return KeyStore with the certificate and private key
 * @throws GeneralSecurityException 
 */
public static KeyStore createCertificateAuthority(String keyAlgorithm, int keyLength, char[] storePassword, char[] keyPassword, String alias,
        String signatureAlgorithm, String issuer, Date validFrom, Date validTo)
        throws GeneralSecurityException {
    String subject = issuer;
    String subjectAltName = null;
    String subjectIPAddress = null;//"127.0.0.1";
    KeyPair keyPair = SecurityUtils.generateKeyPair(keyAlgorithm, keyLength);
    X509Certificate x509Certificate = CertificateUtils.generateV3Certificate(
            new X500Principal(issuer), new X500Principal(subject),
            false, false, subjectAltName, subjectIPAddress,
            keyPair.getPublic(), keyPair.getPrivate(), validFrom, validTo, signatureAlgorithm);
    x509Certificate.checkValidity(new Date());
    x509Certificate.verify(keyPair.getPublic());

    X509Certificate[] chain = new X509Certificate[1];
    chain[0] = x509Certificate;
    KeyStore keyStoreSigningKey = SecurityUtils.createKeyStore(storePassword);
    keyStoreSigningKey.setKeyEntry(alias, keyPair.getPrivate(), keyPassword, chain);
    return keyStoreSigningKey;
}

/**
 * Generate RCA 1024bit private and public keys pair
 * 
 * @param algorithm the standard string name of the algorithm. i.e. "RSA"
 * @param keySize algorithm-specific metric, such as modulus length, specified in number of bits. i.e. 1024,2048,4096 for RSA
 * @return
 * @throws NoSuchAlgorithmException
 */
public static KeyPair generateKeyPair(String algorithm, int keySize) throws NoSuchAlgorithmException {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
    kpg.initialize(keySize);
    return kpg.generateKeyPair();
}

/**
 * Create new key store
 * 
 * @param storePassword
 * @return
 * @throws KeyStoreException
 * @throws NoSuchAlgorithmException
 * @throws CertificateException
 */
public static KeyStore createKeyStore(char[] storePassword) throws KeyStoreException, NoSuchAlgorithmException, CertificateException {
    // Instantiate KeyStore
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

    // Load keystore
    try {
        keyStore.load(null, storePassword);
    } catch (IOException e) { //theoretically should never happen
        throw new KeyStoreException(e);
    }

    return keyStore;
}

或者我有的其他类似方法:

/**
 * Creates a new key pair and self-signed certificate.
 * example params: keyAlgName = "RSA", sigAlgName = "SHA1WithRSA", keysize = 2048
 * Example: x500Name=new X500Name(commonName, organizationalUnit, organization, city, state, country);
 * @param keyStore
 * @param alias
 * @param keyPass 
 * @param keyAlgName 
 * @param sigAlgName 
 * @param keysize 
 * @param principal 
 * @param startDate 
 * @param validityDays 
 * @return KeyStore object
 * @throws Exception  
 */
public static KeyStore generateKeyPair(KeyStore keyStore, String alias, char[] keyPass,
        String keyAlgName, String sigAlgName, int keysize,
        X500Principal principal, Date startDate, int validityDays)
        throws Exception {
    KeyStore keyStore2 = keyStore;
    if (keyStore2 == null) {
        keyStore2 = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore2.load(null, null);
    }

    if (keyStore2.containsAlias(alias)) {
        MessageFormat form = new MessageFormat("Key pair not generated, alias <alias> already exists");
        Object[] source = {alias};
        throw new Exception(form.format(source));
    }

    X509Certificate[] chain = new X509Certificate[1];

    //CertAndKeyGen keyPair = new CertAndKeyGen(keyAlgName, sigAlgName);
    //keyPair.generate(keysize);
    //X500Name x500Name=new X500Name(commonName, organizationalUnit, organization, city, state, country);
    //chain[0] = keyPair.getSelfCertificate(x500Name, startDate, (long)validityDays*24*3600);
    KeyPair keyPair = SecurityUtils.generateKeyPair(keyAlgName, keysize);
    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(startDate);
    cal.add(Calendar.DATE, validityDays);
    Date endDate = cal.getTime();
    chain[0] = generateV3Certificate(principal, principal, false, true, null, null, keyPair.getPublic(), keyPair.getPrivate(), startDate, endDate, sigAlgName);

    keyStore2.setKeyEntry(alias, keyPair.getPrivate(), keyPass, chain);
    return keyStore2;
}

/**
 * Generate V3 Certificate.
 * @param issuer issuer
 * @param subject subject
 * @param useForServerAuth use for server auth flag
 * @param useForClientAuth use for client auth flag
 * @param subjectAltName subject alt name
 * @param subjectIPAssress subject IP address
 * @param publicKey public key
 * @param privateKey private key
 * @param from certificate validity first date
 * @param to certificate validity last date
 * @param signatureAlgorithm signature algorithm
 * @return X509Certificate object
 * @throws GeneralSecurityException GeneralSecurityException
 */
public static X509Certificate generateV3Certificate(X500Principal issuer, X500Principal subject,
        boolean useForServerAuth, boolean useForClientAuth,
        String subjectAltName, String subjectIPAssress, PublicKey publicKey, PrivateKey privateKey,
        Date from, Date to, String signatureAlgorithm) throws GeneralSecurityException {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

    X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

    certGen.setSerialNumber(new BigInteger(UUID.randomUUID().toString().replaceAll("-", ""), 16));
    certGen.setSubjectDN(subject);
    certGen.setIssuerDN(issuer);
    certGen.setNotBefore(from);
    certGen.setNotAfter(to);
    certGen.setPublicKey(publicKey);
    certGen.setSignatureAlgorithm(signatureAlgorithm);

    certGen.addExtension(X509Extensions.BasicConstraints, true, issuer.equals(subject) ? new BasicConstraints(1) : new BasicConstraints(false));
    if (!issuer.equals(subject)) {
        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature
                | KeyUsage.keyEncipherment | (useForServerAuth ? KeyUsage.keyCertSign | KeyUsage.cRLSign : 0)));
    }
    if (useForServerAuth) {
        certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth));
    }
    if (useForClientAuth) {
        certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth));
    }
    if (subjectAltName != null) {
        certGen.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(
                new GeneralName(GeneralName.rfc822Name, subjectAltName)));
    }
    if (subjectIPAssress != null) {
        certGen.addExtension(X509Extensions.SubjectAlternativeName, true, new GeneralNames(
                new GeneralName(GeneralName.iPAddress, subjectIPAssress)));
    }

    return certGen.generate(privateKey);
}

关于java - 如何生成要作为参数发送给 KeyStore.PrivateKeyEntry 的证书链?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6692671/

相关文章:

java - 没有硬编码值的外观和感觉

c# - 读取 ASN.1 DER 编码的 RSA 公钥

java - BlowFish 解密 - nCFB 模式

javascript - 根据密码在javascript中生成RSA key 对

swift - 在 MacOS 上使用 swift 3 在登录钥匙串(keychain)中安装证书

java - 添加自签名证书 OkHttpClient

java - 为链表类的子字符串开发替换方法

java - 在 JBDS/JBoss 工具中使用 Hibernate

JNLP 版本控制的 Java Webstart 证书问题

java - 带有 Appodeal 的原生广告