铁马冰河2000

导航

Java数字签名-RSA算法

数字签名

  数字签名是带有密钥(公钥、私钥)的消息摘要算法。主要作用是验证数据的完整性、认证数据来源、抗否认。在数字签名的实现中我们使用私钥签名、公钥验证。常用的数字签名算法包括RSA、DSA、ECDSA。

RSA

  该算法是数字签名的经典算法。主要包括MD和SHA两类。

应用场景:

   Java实现RSA数字签名如下:

============================================================================RSA数字签名工具类:

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class DigitalSignRSA {
    //公钥
    private static final String PUBLIC_KEY = "RSAPublicKey";
    //私钥
    private static final String PRIVATE_KEY = "RSAPrivateKey";
 
    /** 初始化密钥对
     * @return Map 密钥对Map
     * @throws Exception
     */
    public static Map<String, Object> initKey() {
        try {
            //实例化密钥对生成器
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            // 初始化密钥对生成器,密钥大小为96-1024位
            keyPairGenerator.initialize(512, new SecureRandom());
            //生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            //公钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            //私钥
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            //将密钥对存储在Map中
            Map<String, Object> keyMap = new HashMap<String, Object>(2);
            keyMap.put(PUBLIC_KEY, publicKey);
            keyMap.put(PRIVATE_KEY, privateKey);
            return keyMap;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    /** 执行数字签名【私钥签名】
     * @param data 待加密数据
     * @param privKey  私钥
     * @return byte[] 加密数据
     * @throws Exception
     */
    public static byte[] digitalSign(byte[] data, byte[] privKey) {
        try {
            PrivateKey privateKey = (PrivateKey) KeyFactory.getInstance("RSA")
                    .generatePrivate(new PKCS8EncodedKeySpec(privKey));
            Signature signature = Signature.getInstance("MD5WithRSA");
            signature.initSign(privateKey);
            signature.update(data);
            return signature.sign();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }
 
    /** 验证签名【公钥验证】
     * @param data 待解密数据
     * @param pubKey  公钥
     * @return byte[] 解密数据
     * @throws Exception
     */
    public static boolean signVerify(byte[] data, byte[] rsaData, byte[] pubKey) {
        try {
            PublicKey publicKey = (PublicKey) KeyFactory.getInstance("RSA")
                    .generatePublic(new X509EncodedKeySpec(pubKey));
            Signature signature = Signature.getInstance("MD5WithRSA");
            signature.initVerify(publicKey);
            signature.update(data);
            return signature.verify(rsaData);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return false;
    }
 
    /** 取得私钥
     * @param keyMap 密钥Map
     * @return byte[] 私钥
     * @throws Exception
     */
    public static byte[] getPrivateKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }
 
    /** 取得公钥
     * @param keyMap 密钥Map
     * @return byte[] 公钥
     * @throws Exception
     */
    public static byte[] getPublicKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }
}

============================================================================RSA数字签名工具测试类:

    @Test
    public void test_DigitalSignRSA() {
        //公钥
        byte[] publicKey;
        //私钥
        byte[] privateKey;
 
        //初始化密钥
        //生成密钥对
        Map<String, Object> keyMap = DigitalSignRSA.initKey();
        publicKey = DigitalSignRSA.getPublicKey(keyMap);
        privateKey = DigitalSignRSA.getPrivateKey(keyMap);
        System.out.println("RSA公钥:\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(publicKey));
        System.out.println("RSA私钥:\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(privateKey));
 
        System.out.println();
        String msgA2B = "What can I do for you?";
        //执行数字签名【私钥签名】
        byte[] encodeMsgA2B = DigitalSignRSA.digitalSign(msgA2B.getBytes(), privateKey);
        System.out.println("JDK RSA签名::\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(encodeMsgA2B));
        //验证签名【公钥验证】
        boolean bool = DigitalSignRSA.signVerify(msgA2B.getBytes(), encodeMsgA2B, publicKey);
        System.out.println("数字签名是否有效?:\n" + bool);
    }

 

posted on 2022-01-23 22:48  铁马冰河2000  阅读(865)  评论(1编辑  收藏  举报