java实现Ed25519算法加签验签

时间:2021-6-4 作者:qvyue

Ed25519是一个数字签名算法,签名和验证的性能都极高。

gradle引入jar包依赖:

compile("org.whispersystems:curve25519-android:0.5.0")
compile("net.i2p.crypto:eddsa:0.3.0")

新建TestUtil工具类

package com.ly.mp.project.utils;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.util.Base64;

import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;

public class TestUtil {
    /**
     * ed25519生成密钥对
     * @return
     */
    public static KeyPair ed25519GerateKeyPair() {
        KeyPairGenerator edDsaKpg = new KeyPairGenerator();
        KeyPair keyPair = edDsaKpg.generateKeyPair();
        return keyPair;
    }
    /**
     * ed25519签名
     * @param privateKey
     * @param data
     * @throws Exception 
     */
    public static String ed25519Sign(PrivateKey privateKey, byte[] data) throws Exception {
        EdDSAEngine edEng  = new EdDSAEngine();
        //edEng.initSign(getEd25519PrivateKey(privateKey));
        edEng.initSign(privateKey);
        edEng.setParameter(EdDSAEngine.ONE_SHOT_MODE);
        edEng.update(data);
        byte[] enEdata =  edEng.sign();
        return Base64.getEncoder().encodeToString(enEdata);
    }
    
    public static PrivateKey getEd25519PrivateKey(String privateKey) {
        EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
        return new EdDSAPrivateKey(new EdDSAPrivateKeySpec(Base64.getDecoder().decode(privateKey), spec)); 
    }
    
    
    
    /**
     * ed25519验签
     * @param data
     * @param signData
     * @return
     * @throws SignatureException
     * @throws InvalidAlgorithmParameterException
     * @throws InvalidKeyException
     */
    public static Boolean ed25519VerifySign(String publicKey, String data, String signData) throws SignatureException, InvalidAlgorithmParameterException, InvalidKeyException {
        EdDSAEngine edEng  = new EdDSAEngine();
        EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);  
        byte[] publicKeyByte = Base64.getDecoder().decode(publicKey);
        PublicKey pk = new EdDSAPublicKey(new EdDSAPublicKeySpec(publicKeyByte, spec));
        edEng.initVerify(pk);
        edEng.setParameter(EdDSAEngine.ONE_SHOT_MODE);
        edEng.update(data.getBytes());
        Boolean isSuccess = edEng.verify(Base64.getDecoder().decode(signData));
        return isSuccess;
    }
    
    public static Boolean ed25519VerifySign(PublicKey publicKey, String data, String signData) throws SignatureException, InvalidAlgorithmParameterException, InvalidKeyException {
        EdDSAEngine edEng  = new EdDSAEngine();
        edEng.initVerify(publicKey);
        edEng.setParameter(EdDSAEngine.ONE_SHOT_MODE);
        edEng.update(data.getBytes());
        Boolean isSuccess = edEng.verify(Base64.getDecoder().decode(signData));
        return isSuccess;
    }
    
    public static void main(String[] args) {
        KeyPair keyPair = VaultPrefixUtil.ed25519GerateKeyPair();
        EdDSAPrivateKey pv = (EdDSAPrivateKey) keyPair.getPrivate();
        String privateKey = Base64.getEncoder().encodeToString(pv.getSeed());
        String publicKey = Base64.getEncoder().encodeToString(pv.getAbyte());
        System.out.println("privateKey:" + privateKey);
        System.out.println("publicKey:" + publicKey);
        
//      byte[] pb = Base64.getDecoder().decode(publicKey);
//       EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);  
//       EdDSAPublicKey pk = new EdDSAPublicKey(new EdDSAPublicKeySpec(pb, spec));
        
        String data = "123我";
        String signData = "";
        try {
            signData = VaultPrefixUtil.ed25519Sign(pv, data.getBytes("UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        System.out.println("signData:" + signData);
        
        System.out.println("privateKeyLength=" + Base64.getDecoder().decode(privateKey).length);
        
        try {
            Boolean flag = VaultPrefixUtil.ed25519VerifySign(publicKey, data, signData);
            System.out.println(flag);
        } catch (InvalidKeyException | SignatureException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
    }
}

运行main方法输出如下:

privateKey:1thlaSJ3ttRZwP7qYPFvM2p9QBTsPNiiisB7eQs8G+U=
publicKey:3YhBvpTK+NcpVl8ASJr90Yfcvx3Oj28EQ5FTcO9P9QI=
signData:Luyg26nhRtWNwuMKiWOcivnSiWhqSN7K7TER4oZ/xKOOLKwnC6optI6MOiywLyKYXYdvmeJeS17dmwR94/N+Cw==
privateKeyLength=32
true

可以看到加签验签都是成功的。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。