java - 如何从 Java 中的文件生成 PublicKey 对象

标签 java encryption rsa bouncycastle public-key-encryption

我有一个包含 RSA 公钥的文件(使用 ssh-keygen 生成)。我想读取文件并生成一个 PublicKey 对象。

在此之前我转换了文件,因为读取原始文件似乎是不可能的:

# http://unix.stackexchange.com/questions/220354/how-to-convert-public-key-from-pem-to-der-format/220356#220356
ssh-keygen -f ~/.ssh/id_rsa.pub -e -m PEM > ~/.ssh/id_rsa.pub.pem
openssl rsa -RSAPublicKey_in -in ~/.ssh/id_rsa.pub.pem -inform PEM -outform DER -out ~/.ssh/id_rsa.pub.der -RSAPublicKey_out

来自 Java - Encrypt String with existing public key file我定义了函数readFileBytes:

public static byte[] readFileBytes(String filename) throws IOException {
    Path path = Paths.get(System.getProperty("user.home") + filename);
    return Files.readAllBytes(path);
}

现在我想读取文件并生成 PublicKey 对象,但我找不到这样做的方法; java.security.spec.RSAPublicKeySpec 不提供合适的构造函数并且 java.security.spec.X509EncodedKeySpec 抛出错误 java.security.spec.InvalidKeySpecException: java .security.InvalidKeyException: IOException: algid 解析错误,不是序列:

//RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(readFileBytes("/.ssh/id_rsa.pub.der"));
// No fitting construktor

X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(readFileBytes("/.ssh/id_rsa.pub.der"));
// Gives: "algid parse error, not a sequence"

最佳答案

我有一个项目,其中 (RSA) 加密是必需的,这就是我在给定 publicKeybyte 的情况下重建 publicKey 的方式数组,刚刚从文件中读取。

public PublicKey reconstruct_public_key(String algorithm, byte[] pub_key) {
    PublicKey public_key = null;

    try {
        KeyFactory kf = KeyFactory.getInstance(algorithm);
        EncodedKeySpec pub_key_spec = new X509EncodedKeySpec(pub_key);
        public_key = kf.generatePublic(pub_key_spec);
    } catch(NoSuchAlgorithmException e) {
        System.out.println("Could not reconstruct the public key, the given algorithm oculd not be found.");
    } catch(InvalidKeySpecException e) {
        System.out.println("Could not reconstruct the public key");
    }

    return public_key;
}

然后您可以调用类似于此调用的过程,reconstruct_public_key("RSA", readFileBytes("path/to/your/publicKey/file"));

编辑:我尝试自己做(将公钥写入文件,读取该文件并重建 key )。这有效:

public static void main(String args[]) {
    String path = "./pub_key_test.txt";

    // Generate a keypair to write to file
    KeyPair kp = generate_key();
    PublicKey pub_key = kp.getPublic();
    File file = new File(path);

    try {
        // Write to file
        file.createNewFile();
        FileOutputStream out = new FileOutputStream(path);

        out.write(pub_key.getEncoded()); // Write public key to the file
        out.close();

        // Read from file
        FileInputStream in = new FileInputStream(path);
        byte[] pub_key_arr = new byte[in.available()];
        in.read(pub_key_arr, 0, in.available());
        in.close();

        // Reconstruct public key
        PublicKey reconstructed_pub_key = reconstruct_public_key("RSA", pub_key_arr);
    } catch(IOException e) {
        System.out.println("Could not open the file : " + e.getStackTrace());
    }
}

这是generate_key过程:

public KeyPair generate_key() {
    while(true) { // Else the compiler will complain that this procedure does not always return a "KeyPair"
        try {
            final KeyPairGenerator key_generator = KeyPairGenerator.getInstance("RSA");
            key_generator.initialize(2048); // Keys of 2048 bits (minimum key length for RSA keys) are safe enough (according to the slides 128bit keys > 16 years to brute force it)

            final KeyPair keys = key_generator.generateKeyPair();
            return keys;
        } catch(NoSuchAlgorithmException e) {
            System.out.println("The given encryption algorithm (RSA) does not exist. -- generate_key() - Cryptography.");
        }
    }
}

如果您对此进行测试,您将看到 publicKey 已成功重构。

编辑:我试着自己做,使用 ssh-keygen 工具。这就是我所做的:

  • 首先我生成了一个RSA私钥(.PEM格式)
  • 将公钥部分输出为.DER格式,供Java使用。

我是这样转换的,和你的有点不同:

openssl rsa -in private_key_file.pem -pubout -outform DER -out java_readable_file.der

我把文件读成here ,这与您的差别不大。我对此进行了测试,Java 成功地重建了公钥。

关于java - 如何从 Java 中的文件生成 PublicKey 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32117087/

相关文章:

java.lang.UnsatisfiedLinkError : Native method not found: package. ClassName.stringFromJNI:()Ljava/lang/String;

encryption - 分层加密

c++ - RSA解密C++的私钥

c - 长文件的RSA加密/解密

php - 我的数据库无法使用 RSA 加密

java - BouncycaSTLe:如何创建 RSA 私钥的加密 PKCS8 表示?

java - 使用 PowerMock 和 Mockito 模拟静态方法

java - 无法从对象转换为 boolean 值

java - Spring WebSocket MessageMapping 不起作用

.net-core - 如何将公钥导入RSA以在.net core中加密