利用RSA生成数字签名以及验签核心代码实现

1.创建BaseUtil文件,代码如下:

package com.itmuch.cloud.util;

import java.io.ByteArrayOutputStream;

/**
 * base64 format encoding & decoding
 */
public class Base64Util {

	private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D',
			'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
			'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
			'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
			'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
			'4', '5', '6', '7', '8', '9', '+', '/' };

	private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
			60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
			10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
			-1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
			38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
			-1, -1 };

	private Base64Util(){
	}

	public static String encode(byte[] data){
		StringBuffer sb = new StringBuffer();
		int len = data.length;
		int i = 0;
		int b1, b2, b3;

		while (i < len) {
			b1 = data[i++] & 0xff;
			if (i == len) {
				sb.append(base64EncodeChars[b1 >>> 2]);
				sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
				sb.append("==");
				break;
			}
			b2 = data[i++] & 0xff;
			if (i == len) {
				sb.append(base64EncodeChars[b1 >>> 2]);
				sb.append(base64EncodeChars[((b1 & 0x03) << 4)
						| ((b2 & 0xf0) >>> 4)]);
				sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
				sb.append("=");
				break;
			}
			b3 = data[i++] & 0xff;
			sb.append(base64EncodeChars[b1 >>> 2]);
			sb.append(base64EncodeChars[((b1 & 0x03) << 4)
					| ((b2 & 0xf0) >>> 4)]);
			sb.append(base64EncodeChars[((b2 & 0x0f) << 2)
					| ((b3 & 0xc0) >>> 6)]);
			sb.append(base64EncodeChars[b3 & 0x3f]);
		}
		return sb.toString();
	}

	public static byte[] decode(String str){
		byte[] data = str.getBytes();
		int len = data.length;
		ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
		int i = 0;
		int b1, b2, b3, b4;

		while (i < len) {

			/* b1 */
			do {
				b1 = base64DecodeChars[data[i++]];
			} while (i < len && b1 == -1);
			if (b1 == -1) {
				break;
			}

			/* b2 */
			do {
				b2 = base64DecodeChars[data[i++]];
			} while (i < len && b2 == -1);
			if (b2 == -1) {
				break;
			}
			buf.write(((b1 << 2) | ((b2 & 0x30) >>> 4)));

			/* b3 */
			do {
				b3 = data[i++];
				if (b3 == 61) {
					return buf.toByteArray();
				}
				b3 = base64DecodeChars[b3];
			} while (i < len && b3 == -1);
			if (b3 == -1) {
				break;
			}
			buf.write((((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));

			/* b4 */
			do {
				b4 = data[i++];
				if (b4 == 61) {
					return buf.toByteArray();
				}
				b4 = base64DecodeChars[b4];
			} while (i < len && b4 == -1);
			if (b4 == -1) {
				break;
			}
			buf.write((((b3 & 0x03) << 6) | b4));
		}
		return buf.toByteArray();
	}
}
 

2.具体代码实现:

package com.itmuch.cloud.util;

import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.*;
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;

/**
 * 功能描述,RSA生成私钥公钥加解密工具类
 * @author:mischen
 * @date:2020/4/5 17:19
 */
public class RSAUtils {

    /** */
    /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";


    /** */
    /**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";


    private static Map<Integer, String> keyMap = new HashMap<Integer, String>();  //用于封装随机产生的公钥与私钥
    public static void main(String[] args) throws Exception {
        //生成公钥和私钥
        genKeyPair();
        //加密字符串
        String message = "mischen.14588@";
        System.out.println("随机生成的公钥为:" + keyMap.get(0));
        System.out.println("随机生成的私钥为:" + keyMap.get(1));
        //用公钥进行加密
        String messageEn = encrypt(message,keyMap.get(0));
        System.out.println(message + "\t加密后的字符串为:" + messageEn);
        //用私钥进行解密
        String messageDe = decrypt(messageEn,keyMap.get(1));
        System.out.println("还原后的字符串为:" + messageDe);

        String merchantSign = sign(message.getBytes(),keyMap.get(1));
        System.out.println("数字签名后的字符串为:" + merchantSign);
        boolean verify = verify(message.getBytes(),keyMap.get(0),merchantSign);
        System.out.println("校验数字签名的结果为:" + verify);
    }

    /**
     * 随机生成密钥对
     * @throws NoSuchAlgorithmException
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器,密钥大小为96-1024位
        keyPairGen.initialize(1024,new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到私钥字符串
        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
        // 将公钥和私钥保存到Map
        keyMap.put(0,publicKeyString);  //0表示公钥
        keyMap.put(1,privateKeyString);  //1表示私钥
    }
    /**
     * RSA公钥加密
     *
     * @param str
     *            加密字符串
     * @param publicKey
     *            公钥
     * @return 密文
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static String encrypt( String str, String publicKey ) throws Exception{
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
        return outStr;
    }

    /**
     * RSA私钥解密
     *
     * @param str
     *            加密字符串
     * @param privateKey
     *            私钥
     * @return 铭文
     * @throws Exception
     *             解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception{
        //64位解码加密后的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
        //base64编码的私钥
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }
    /** */
    /**
     * <p>
     * 用私钥对信息生成数字签名
     * </p>
     *
     * @param data 已加密数据
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64Util.decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateK);
        signature.update(data);
        return Base64Util.encode(signature.sign());
    }

    /** */
    /**
     * <p>
     * 校验数字签名
     * </p>
     *
     * @param data 已加密数据
     * @param publicKey 公钥(BASE64编码)
     * @param sign 数字签名
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {
        byte[] keyBytes = Base64Util.decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicK);
        signature.update(data);
        return signature.verify(Base64Util.decode(sign));
    }


}

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、数字签名原理 用RSA算法做数字签名,总的来说,就是签名者用私钥参数d加密,也就是签名;验证者用签字者的公钥参数e解密来完成认证。 下面简要描述数字签名和认证的过程。 (1)、生成密钥 为用户随机生成一对密钥:公钥(e,n)和私钥(d,n). (2)、签名过程 a) 计算消息的散列值H(M). b) 用私钥(d,n)加密散列值:s=(H(M)) mod n,签名结果就是s. c) 发送消息和签名(M,s). (3)、认证过程 a) 取得发送方的公钥(e,n). b) 解密签名s:h=s mod n. c) 计算消息的散列值H(M). d) 比较,如果h=H(M),表示签名有效;否则,签名无效。 根据上面的过程,我们可以得到RSA数字签名的框图如图2-1: 图 2-1 RSA数字签名框图 2、 假设Alice想和Bob通信,以本地两个文件夹Alice和Bob模拟两个用户,实现消息M和签名的模拟分发 (1)、Alice通过RSA算法生成一对密钥:公钥(e,n)和私钥(d,n),将公私钥分别存入pubKey.txt和priKey.txt中。 pubKey.txt中公钥如下: priKey.txt中私钥如下: (2)、将Alice中的pubKey.txt拷到Bob中,模拟公玥的分发。 (3)、将Alice中的消息info.txt做散列,将散列后的值存入hashInfo.txt中。 (4)、将Alice中的消息hashInfo.txt和签名sign.txt拷到Bob中,实现M密文状态下的签名与模拟分发、消息传递。 (5)Bob取得公钥pubKey.txt,用公钥解密签名,计算消息的散列值H(M).比较,如果h=H(M),表示签名有效;否则,签名无效。 后台运行结果如下:
RSA数字签名是一种常用的数字签名算法,实现代码如下: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/rsa.h> #include <openssl/pem.h> // 生成RSA密钥对 int generate_key(char *pub_key_file, char *pri_key_file, int key_len) { int ret = 0; RSA *rsa = NULL; BIGNUM *bne = NULL; BIO *bp_public = NULL, *bp_private = NULL; char *pub_key = NULL, *pri_key = NULL; // 生成RSA密钥对 bne = BN_new(); ret = BN_set_word(bne, RSA_F4); if (ret != 1) { printf("BN_set_word failed\n"); return -1; } rsa = RSA_new(); ret = RSA_generate_key_ex(rsa, key_len, bne, NULL); if (ret != 1) { printf("RSA_generate_key_ex failed\n"); return -1; } // 将密钥对输出到文件 bp_public = BIO_new(BIO_s_file()); bp_private = BIO_new(BIO_s_file()); ret = BIO_write_filename(bp_public, pub_key_file); if (ret <= 0) { printf("BIO_write_filename public failed\n"); return -1; } ret = PEM_write_bio_RSAPublicKey(bp_public, rsa); if (ret != 1) { printf("PEM_write_bio_RSAPublicKey failed\n"); return -1; } ret = BIO_write_filename(bp_private, pri_key_file); if (ret <= 0) { printf("BIO_write_filename private failed\n"); return -1; } ret = PEM_write_bio_RSAPrivateKey(bp_private, rsa, NULL, NULL, 0, NULL, NULL); if (ret != 1) { printf("PEM_write_bio_RSAPrivateKey failed\n"); return -1; } RSA_free(rsa); BN_free(bne); BIO_free_all(bp_public); BIO_free_all(bp_private); return 0; } // RSA数字签名 int rsa_sign(char *data, int data_len, char *pri_key_file, char *signature, int *sig_len) { int ret = 0; RSA *rsa = NULL; FILE *fp = NULL; char *pri_key = NULL; // 读取密钥文件 fp = fopen(pri_key_file, "rb"); if (fp == NULL) { printf("open private key file failed\n"); return -1; } rsa = PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL); if (rsa == NULL) { printf("PEM_read_RSAPrivateKey failed\n"); return -1; } // RSA数字签名 ret = RSA_sign(NID_sha256, (unsigned char *)data, data_len, (unsigned char *)signature, (unsigned int *)sig_len, rsa); if (ret != 1) { printf("RSA_sign failed\n"); return -1; } RSA_free(rsa); fclose(fp); return 0; } // RSA数字验签 int rsa_verify(char *data, int data_len, char *pub_key_file, char *signature, int sig_len) { int ret = 0; RSA *rsa = NULL; FILE *fp = NULL; char *pub_key = NULL; // 读取密钥文件 fp = fopen(pub_key_file, "rb"); if (fp == NULL) { printf("open public key file failed\n"); return -1; } rsa = PEM_read_RSAPublicKey(fp, &rsa, NULL, NULL); if (rsa == NULL) { printf("PEM_read_RSAPublicKey failed\n"); return -1; } // RSA数字验签 ret = RSA_verify(NID_sha256, (unsigned char *)data, data_len, (unsigned char *)signature, sig_len, rsa); if (ret != 1) { printf("RSA_verify failed\n"); return -1; } RSA_free(rsa); fclose(fp); return 0; } ``` 使用示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { int ret = 0; char *pub_key_file = "rsa_public_key.pem"; char *pri_key_file = "rsa_private_key.pem"; char *data = "Hello, World!"; char signature[1024] = {0}; int sig_len = 0; // 生成RSA密钥对 ret = generate_key(pub_key_file, pri_key_file, 2048); if (ret != 0) { printf("generate_key failed\n"); return -1; } // RSA数字签名 ret = rsa_sign(data, strlen(data), pri_key_file, signature, &sig_len); if (ret != 0) { printf("rsa_sign failed\n"); return -1; } printf("signature: "); for (int i = 0; i < sig_len; i++) { printf("%02x", signature[i]); } printf("\n"); // RSA数字验签 ret = rsa_verify(data, strlen(data), pub_key_file, signature, sig_len); if (ret != 0) { printf("rsa_verify failed\n"); return -1; } printf("verify success\n"); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值