Java-在密钥库中存储密钥对

时间:2020-04-13 19:13:51

标签: java encryption

我正在实施混合加密项目,并且已经为发送方和接收方密钥(私有和公共)生成了两个密钥对。我在文件中有这些密钥。

密钥对生成代码

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;

import Decoder.BASE64Encoder;

public class GenerateRSAKeys{

    public static void main(String[] args)
    {



        String publicKeyFilename = null;
        String privateKeyFilename = null;

        publicKeyFilename = "C:\\Users\\imjme1\\Desktop\\Work_backup\\FMS\\EPM_FILE_ENCRYPTION\\NIFT_SOLUTION\\sender_keys\\receiver_publicKey";
        privateKeyFilename = "C:\\Users\\imjme1\\Desktop\\Work_backup\\FMS\\EPM_FILE_ENCRYPTION\\NIFT_SOLUTION\\sender_keys\\receiver_privateKey";

        GenerateRSAKeys generateRSAKeys = new GenerateRSAKeys();

        generateRSAKeys.generate(publicKeyFilename, privateKeyFilename);

    }

    private void generate (String publicKeyFilename, String privateFilename){

        try {

            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

            // Create the public and private keys
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
            BASE64Encoder b64 = new BASE64Encoder();

            SecureRandom random = createFixedRandom();
            generator.initialize(1024, random);

            KeyPair pair = generator.generateKeyPair();
            Key pubKey = pair.getPublic();
            Key privKey = pair.getPrivate();

            System.out.println("publicKey : " + b64.encode(pubKey.getEncoded()));
            System.out.println("privateKey : " + b64.encode(privKey.getEncoded()));

            BufferedWriter out = new BufferedWriter(new FileWriter(publicKeyFilename));
            out.write(b64.encode(pubKey.getEncoded()));
            out.close();

            out = new BufferedWriter(new FileWriter(privateFilename));
            out.write(b64.encode(privKey.getEncoded()));
            out.close();


        }
        catch (Exception e) {
            System.out.println(e);
        }
    }

    public static SecureRandom createFixedRandom()
    {
        return new FixedRand();
    }

    private static class FixedRand extends SecureRandom {

        MessageDigest sha;
        byte[] state;

        FixedRand() {
            try
            {
                this.sha = MessageDigest.getInstance("SHA-1");
                this.state = sha.digest();
            }
            catch (NoSuchAlgorithmException e)
            {
                throw new RuntimeException("can't find SHA-1!");
            }
        }

        public void nextBytes(byte[] bytes){

            int    off = 0;

            sha.update(state);

            while (off < bytes.length)
            {                
                state = sha.digest();

                if (bytes.length - off > state.length)
                {
                    System.arraycopy(state, 0, bytes, off, state.length);
                }
                else
                {
                    System.arraycopy(state, 0, bytes, off, bytes.length - off);
                }

                off += state.length;

                sha.update(state);
            }
        }
    }

}

现在,我需要保护这些密钥(可能不是直接在任何磁盘上)。

我已经在互联网上搜索了此案;将密钥保存到密钥库中是一种保护密钥并在读取用于加密和解密的密钥时使用相同密钥库的方法。

有人可以建议我如何在密钥存储区中保存公钥和私钥以及如何在Java中读取它吗?

1 个答案:

答案 0 :(得分:0)

Java KeyStore API(和基础提供程序)不支持存储密钥对 -即私钥和公钥(可以使用用于加密和验证之类的公钥操作)。它确实支持存储私钥和公​​钥的证书链。证书链只能包含一个证书,特别是如果该证书是自签名证书(从定义上来说,它是一个链本身)。这正是命令行keytool -genkeypair所做的:它生成一个密钥对,并在(指定的或默认的)密钥库文件中存储私钥和公​​钥的自签名证书。

如果仅使用“标准” JRE,则在代码中创建自签名(或其他)证书并不容易。

但是,如果您添加了BouncyCastle(显然这样做了,或者发布的代码不起作用),则具有许多适用的功能。有关使用 only bcprov(旧的,已弃用的X509V3CertificateGenerator)生成证书的简单示例,请参见我的JAVA API to create a keystore and attaching a csr and keypair to it -但按照我在此处建议的操作,但未显示:不要先创建不需要的CSR,而要使用所需的名称和公钥创建证书。

最好,如果您也有或可以获取bcpkix,请使用X509v3CertificateBuilder。请参见Self signed X509 Certificate with Bouncy Castle in JavaGenerating X509 Certificate using Bouncy Castle Java上的示例。

要写出和读回包含此数据的密钥库文件,请参阅上面链接的Javadoc。注意Java传统上默认为JKS格式的文件,您会在此处和Web上的其他地方找到许多较早的答案,这些假设都假设是这样,但是自2017年Java 9起,它默认为PKCS12格式,这不仅是标准格式,因此(主要是)可互操作但也更安全(使用更好的PBKDF算法)。

但是,您的代码使用了完全伪造的随机生成器,因此每次生成相同的密钥对。鉴于此,实际上不需要存储它,因为您随时可以随时重新生成它。实际上,即使拥有这些密钥对也没有任何好处,因为它完全不提供安全性