web-dev-qa-db-ja.com

秘密鍵で文字列に署名する方法

秘密鍵をSHA1withRSAまたはStringとしてすでに持っている場合、byte[]を使用して文字列の署名を取得するにはどうすればよいですか?

19
xain

私はあなたが言う前にあなたが鍵ペアを知っていて、それで署名/検証したいと言っていると思います。

次のコードをご覧ください。

import Java.security.KeyPair;
import Java.security.KeyPairGenerator;
import Java.security.NoSuchAlgorithmException;
import Java.security.Signature;

import Sun.misc.BASE64Encoder;

public class MainClass {
    public static void main(String[] args) throws Exception {

        KeyPair keyPair = getKeyPair();

        byte[] data = "test".getBytes("UTF8");

        Signature sig = Signature.getInstance("SHA1WithRSA");
        sig.initSign(keyPair.getPrivate());
        sig.update(data);
        byte[] signatureBytes = sig.sign();
        System.out.println("Signature:" + new BASE64Encoder().encode(signatureBytes));

        sig.initVerify(keyPair.getPublic());
        sig.update(data);

        System.out.println(sig.verify(signatureBytes));
    }

    private static KeyPair getKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        return kpg.genKeyPair();
    }
}

ここでは、既知の鍵ペアを提供するためにメソッドgetKeyPair()を変更する必要があります。 Javaキーストア[JKS]からロードできます。

公開鍵または秘密鍵として任意のバイト配列を持つことはできません。それらは関連して生成されるべきです。

46

bouncy-castle を使用してデータに署名し、検証します。

あなたはmavenの依存関係を追加する必要があります:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.56</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.56</version>
</dependency>

RSA秘密鍵または公開鍵をディスクファイルからJavaオブジェクトにロードします

まず、RSA秘密鍵または公開鍵をディスクファイルからJava Bouncy Castleの適切なクラスのオブジェクトにロードできる必要があります。

import Java.io.File;
import Java.io.FileInputStream;
import Java.io.FileNotFoundException;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.InputStreamReader;
import org.Apache.commons.lang3.Validate;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;

public class KeyUtil {

    public static AsymmetricKeyParameter loadPublicKey(InputStream is) {
        SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) readPemObject(is);
        try {
            return PublicKeyFactory.createKey(spki);
        } catch (IOException ex) {
            throw new RuntimeException("Cannot create public key object based on input data", ex);
        }
    }

    public static AsymmetricKeyParameter loadPrivateKey(InputStream is) {
        PEMKeyPair keyPair = (PEMKeyPair) readPemObject(is);
        PrivateKeyInfo pki = keyPair.getPrivateKeyInfo();
        try {
            return PrivateKeyFactory.createKey(pki);
        } catch (IOException ex) {
            throw new RuntimeException("Cannot create private key object based on input data", ex);
        }
    }

    private static Object readPemObject(InputStream is) {
        try {
            Validate.notNull(is, "Input data stream cannot be null");
            InputStreamReader isr = new InputStreamReader(is, "UTF-8");
            PEMParser pemParser = new PEMParser(isr);

            Object obj = pemParser.readObject();
            if (obj == null) {
                throw new Exception("No PEM object found");
            }
            return obj;
        } catch (Throwable ex) {
            throw new RuntimeException("Cannot read PEM object from input data", ex);
        }
    }
}

RSAデジタル署名の作成

        // GIVEN: InputStream prvKeyInpStream
    AsymmetricKeyParameter privKey = KeyUtil.loadPrivateKey(prvKeyInpStream);

    // GIVEN: byte[] messageBytes = ...
    RSADigestSigner signer = new RSADigestSigner(new SHA512Digest());
    signer.init(true, privKey);
    signer.update(messageBytes, 0, messageBytes.length);

    try {
        byte[] signature = signer.generateSignature();
    } catch (Exception ex) {
        throw new RuntimeException("Cannot generate RSA signature. " + ex.getMessage(), ex);
    }

RSAデジタル署名の検証

// GIVEN: InputStream pubKeyInpStream
AsymmetricKeyParameter publKey = KeyUtil.loadPublicKey(pubKeyInpStream);

// GIVEN: byte[] messageBytes
RSADigestSigner signer = new RSADigestSigner(new SHA512Digest());
signer.init(false, publKey);
signer.update(messageBytes, 0, messageBytes.length);

// GIVEN: byte[] signature - see code sample above
boolean isValidSignature = signer.verifySignature(signature);
0
public static String sign(String plainText, PrivateKey privateKey) throws Exception {
    Signature privateSignature = Signature.getInstance("SHA256withRSA");
    privateSignature.initSign(privateKey);
    privateSignature.update(plainText.getBytes(UTF_8));

    byte[] signature = privateSignature.sign();

    return Base64.getEncoder().encodeToString(signature);
}

public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {
    Signature publicSignature = Signature.getInstance("SHA256withRSA");
    publicSignature.initVerify(publicKey);
    publicSignature.update(plainText.getBytes(UTF_8));

    byte[] signatureBytes = Base64.getDecoder().decode(signature);

    return publicSignature.verify(signatureBytes);
}
0