使用PEM编码的加密私钥本地签名消息 [英] Using a PEM encoded, encrypted private key to sign a message natively

查看:203
本文介绍了使用PEM编码的加密私钥本地签名消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用PEM(X.509)证书(存储在磁盘上的privateKey.pem文件中)来签署通过Java中的套接字发送的消息,但是在找到一个接近的示例时遇到了很多麻烦。我通常是一个C ++人,他只是踩到这个项目的帮助,所以我把它们整合到我不熟悉API的代码中有点困难。

I'm trying to use a PEM(X.509) certificate (stored in a privateKey.pem file on disk) to sign messages sent via sockets in Java, but am having a lot of trouble finding an example that's close. I'm normally a C++ guy who's just stepping in to help on this project, so it's been a little difficult for me to put it all together into code that works when I'm unfamiliar with the APIs.

不幸的是,我只限于Java(1.6.0 Update 16)标准的方法,所以尽管我使用 BouncyCastle PEMReader ,它对这个特定的项目没有多大帮助。

Unfortunately, I'm limited to methods that come standard with Java (1.6.0 Update 16), so although I found a similar example using BouncyCastle's PEMReader, it hasn't helped much on this particular project.

我的privateKey.pem密钥是passphrase protected,in形式:

My privateKey.pem key is passphrase protected, in the form of:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED DEK-Info:
DES-EDE3-CBC,63A862F284B1280B
[...]
tsjQI4H8lhOBuk+NelHu7h2+uqbBQzwkPoA8IqbPXUz+B/MAGhoTGl4AKPjfm9gu
OqEorRU2vGiSaUPgDaRhdPKK0stxMxbByUi8xQ2156d/Ipk2IPLSEZDXONrB/4O5
[...]
-----END RSA PRIVATE KEY-----

它们的密钥是使用OpenSSL生成的:

They key was generated using OpenSSL:

openssl.exe genrsa -out private_key.pem 4096

我无法在运行之前将此密钥转换为DER或其他格式,所需的任何转换都需要在代码内部完成,因为密钥需要易于更换且格式仍为PEM 。

I am unable to convert this key to a DER or other format prior to runtime, any conversions necessary will need to be done internally in code, as the key needs to be easily replaceable and the format will remain PEM.

我听说过各种各样的事情,我并不完全确定,并且希望SO的集体思想可以帮助把各个方面拉开来。

I've heard a mix of things which I'm not entirely sure about, and was hoping the collective minds here at SO could help pull the pieces together.



我听说它说PEM证书需要Base64解码才能将其转换为可以使用的DER证书。我有一个名为 MiGBase64 的Base64解码工具,但我不完全确定如何/何时需要解码。



I've heard it said that the PEM certificate needs Base64 Decoded to convert it into a DER certificate that can be used. I have a Base64 Decoding tool called MiGBase64 but am not entirely sure how/when this decoding needs done.


我在Java API文档中迷失了,试图追踪存在的15种不同类型的Keys,KeyStores,KeyGenerators,Certificates等,但是我我对他们中的任何一个都不熟悉,无法正确识别我需要使用的内容,以及如何一起使用它们。


I've gotten lost in the Java API docs trying to track down the 15 different types of Keys, KeyStores, KeyGenerators, Certificates, etc that exist, but I'm not familiar enough with any of them to properly identify which I need to be using, and how to use them together.


基本算法看起来很简单,这就是为什么我无法编写同样简单的实现特别令人沮丧的原因:


The basic algorithm seems pretty simple, which is why it has been particularly frustrating that I haven't been able to write an equally simple implementation:

1)从文件中读取privateKey.pem
b $ b 2)将私钥加载到XXX类中,使用密码来解密密钥

3)使用带有Signature类的密钥对象来签署消息

1) Read the privateKey.pem from file
2) Load the private Key into XXX class, using the Passphrase to decrypt the key
3) Use the key object with the Signature class to sign the message




非常感谢您对此的帮助,特别是示例代码。我一直在努力寻找这个问题的有用示例,因为大多数关闭示例都是使用BouncyCastle生成新密钥,或者只是使用不适用于此处的不同形式的密钥/类。



Help with this, especially example code, is greatly appreciated. I've been struggling to find useful examples for this problem, as most 'close' examples are generating new keys, using BouncyCastle, or just otherwise using different forms of keys/classes not applicable here.

这似乎是一个非常简单的问题,但它让我发疯,任何非常简单的答案?

This seems like a really simple problem but it's driving me crazy, any really simple answers?

推荐答案

如果你正在使用BouncyCastle,请尝试以下方法:

If you're using BouncyCastle, try the following:

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyPair;
import java.security.Security;
import java.security.Signature;
import java.util.Arrays;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
import org.bouncycastle.util.encoders.Hex;

public class SignatureExample {

    public static void main(String [] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        String message = "hello world";
        File privateKey = new File("private.pem");
        KeyPair keyPair = readKeyPair(privateKey, "password".toCharArray());

        Signature signature = Signature.getInstance("SHA256WithRSAEncryption");
        signature.initSign(keyPair.getPrivate());
        signature.update(message.getBytes());
        byte [] signatureBytes = signature.sign();
        System.out.println(new String(Hex.encode(signatureBytes)));

        Signature verifier = Signature.getInstance("SHA256WithRSAEncryption");
        verifier.initVerify(keyPair.getPublic());
        verifier.update(message.getBytes());
        if (verifier.verify(signatureBytes)) {
            System.out.println("Signature is valid");
        } else {
            System.out.println("Signature is invalid");
        }
    }

    private static KeyPair readKeyPair(File privateKey, char [] keyPassword) throws IOException {
        FileReader fileReader = new FileReader(privateKey);
        PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword));
        try {
            return (KeyPair) r.readObject();
        } catch (IOException ex) {
            throw new IOException("The private key could not be decrypted", ex);
        } finally {
            r.close();
            fileReader.close();
        }
    }

    private static class DefaultPasswordFinder implements PasswordFinder {

        private final char [] password;

        private DefaultPasswordFinder(char [] password) {
            this.password = password;
        }

        @Override
        public char[] getPassword() {
            return Arrays.copyOf(password, password.length);
        }
    } 
}

这篇关于使用PEM编码的加密私钥本地签名消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆