web-dev-qa-db-ja.com

文字列に署名するためのECDSAアルゴリズムのチュートリアル

JavaでECDSAアルゴリズムを使用して文字列に署名する方法の簡単なチュートリアルを見つけるのを手伝ってくれませんか。しかし、bouncycastleのようなサードパーティのライブラリは使用しません。 JDK 7だけです。単純な例を検索するのは難しいことがわかりました。暗号化は初めてです。


import Java.io.*;
import Java.security.*;

public class GenSig {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        /*
         * Generate a DSA signature
         */

        try {

            /*
             * Generate a key pair
             */

            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "Sun");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "Sun");

            keyGen.initialize(1024, random);

            KeyPair pair = keyGen.generateKeyPair();
            PrivateKey priv = pair.getPrivate();
            PublicKey pub = pair.getPublic();

            /*
             * Create a Signature object and initialize it with the private key
             */

            Signature dsa = Signature.getInstance("SHA1withDSA", "Sun");

            dsa.initSign(priv);

            String str = "This is string to sign";
            byte[] strByte = str.getBytes();
            dsa.update(strByte);

            /*
             * Now that all the data to be signed has been read in, generate a
             * signature for it
             */

            byte[] realSig = dsa.sign();
            System.out.println("Signature: " + new String(realSig));


        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }
}

ECDSA用に変更する方法は?

15
user1379574

ここにあなたの例に基づいた小さな例があります。

注:これはこの回答の元のコードです。更新されたバージョンの次のコードスニペットを参照してください。

import Java.math.BigInteger;
import Java.security.KeyPair;
import Java.security.KeyPairGenerator;
import Java.security.PrivateKey;
import Java.security.PublicKey;
import Java.security.SecureRandom;
import Java.security.Signature;

public class ECDSAExample {

    public static void main(String[] args) throws Exception {
        /*
         * Generate an ECDSA signature
         */

        /*
         * Generate a key pair
         */

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

        keyGen.initialize(256, random);

        KeyPair pair = keyGen.generateKeyPair();
        PrivateKey priv = pair.getPrivate();
        PublicKey pub = pair.getPublic();

        /*
         * Create a Signature object and initialize it with the private key
         */

        Signature dsa = Signature.getInstance("SHA1withECDSA");

        dsa.initSign(priv);

        String str = "This is string to sign";
        byte[] strByte = str.getBytes("UTF-8");
        dsa.update(strByte);

        /*
         * Now that all the data to be signed has been read in, generate a
         * signature for it
         */

        byte[] realSig = dsa.sign();
        System.out.println("Signature: " + new BigInteger(1, realSig).toString(16));

    }
}

更新:非推奨のアルゴリズムを削除するわずかに改善された例を次に示します。また、 RFC 8422で指定されているSECG表記 "secp256r1"を使用して、NIST P-256曲線を明示的に要求します。

import javax.xml.bind.DatatypeConverter;
import Java.security.*;
import Java.security.spec.ECGenParameterSpec;

public class ECDSAExample {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        /*
         * Generate an ECDSA signature
         */

        /*
         * Generate a key pair
         */

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");

        keyGen.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());

        KeyPair pair = keyGen.generateKeyPair();
        PrivateKey priv = pair.getPrivate();
        PublicKey pub = pair.getPublic();

        /*
         * Create a Signature object and initialize it with the private key
         */

        Signature ecdsa = Signature.getInstance("SHA256withECDSA");

        ecdsa.initSign(priv);

        String str = "This is string to sign";
        byte[] strByte = str.getBytes("UTF-8");
        ecdsa.update(strByte);

        /*
         * Now that all the data to be signed has been read in, generate a
         * signature for it
         */

        byte[] realSig = ecdsa.sign();
        System.out.println("Signature: " + DatatypeConverter.printHexBinary(realSig));

    }
}
20
James K Polk
class ECCCipher {
    @Override
    public byte[] sign(PrivateKey privateKey, String message) throws Exception {
        Signature signature = Signature.getInstance("SHA1withECDSA");
        signature.initSign(privateKey);

        signature.update(message.getBytes());

        return signature.sign();
    }

    @Override
    public boolean verify(PublicKey publicKey, byte[] signed, String message) throws Exception {
        Signature signature = Signature.getInstance("SHA1withECDSA");
        signature.initVerify(publicKey);

        signature.update(message.getBytes());

        return signature.verify(signed);
    }
}

========================

public class ECCCipherTest {

private final KeyPairGenerator keygen;

public ECCCipherTest() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
    Security.addProvider(new BouncyCastleProvider());
    this.keygen = KeyPairGenerator.getInstance("ECDSA", "BC");
    keygen.initialize(new ECGenParameterSpec("brainpoolP384r1"));
}

@Test
public void ECC_CipherTest_1() throws Exception {
    String message = "hello world";

    ICipher<PrivateKey, PublicKey> cipher = new ECCCipher();
    KeyPair keyPair = keygen.generateKeyPair();

    byte[] encrypted = cipher.sign(keyPair.getPrivate(), message);

    Assert.assertTrue(cipher.verify(keyPair.getPublic(), encrypted, message));
}

}

これは私のプロジェクトの小さなコードスニペットです。わたしにはできる。 1つのjunitテストも含めました。うまくいけば、これが役立ちます。

秘密鍵とpubkeyをどのようにロードするのか不思議に思う人のために:(注:privKeyはJavaのBigIntegerを表すバイト配列で、pubKeyはバイナリ形式のカーブポイントです)

    @Override
public PrivateKey generatePrivateKey(byte[] keyBin) throws InvalidKeySpecException, NoSuchAlgorithmException {
    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
    KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
    ECNamedCurveSpec params = new ECNamedCurveSpec("secp256k1", spec.getCurve(), spec.getG(), spec.getN());
    ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(new BigInteger(keyBin), params);
    return kf.generatePrivate(privKeySpec);
}

@Override
public PublicKey generatePublicKey(byte[] keyBin) throws InvalidKeySpecException, NoSuchAlgorithmException {
    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
    KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
    ECNamedCurveSpec params = new ECNamedCurveSpec("secp256k1", spec.getCurve(), spec.getG(), spec.getN());
    ECPoint point =  ECPointUtil.decodePoint(params.getCurve(), keyBin);
    ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
    return kf.generatePublic(pubKeySpec);
}
1
linehrr