RSA加密、解密、签名、验签 DSA签名、验签

标签: rsa DSA 加密 解密
7143人阅读 评论(0) 收藏 举报
分类:

重要的事情说三遍,该篇文章主要是验证JAVA的RSA签名、验签的测试代码,主要代码参考 http://xw-z1985.iteye.com/blog/1837376

重要的事情说三遍,该篇文章主要是验证JAVA的RSA签名、验签的测试代码,主要代码参考 http://xw-z1985.iteye.com/blog/1837376

重要的事情说三遍,该篇文章主要是验证JAVA的RSA签名、验签的测试代码,主要代码参考 http://xw-z1985.iteye.com/blog/1837376

下面是C#版的RSA、DSA代码

    using System.Security.Cryptography;
    public class AsymmetricAlgorithmHelper<T>
        where T : AsymmetricAlgorithm, new()
    {
        protected static TResult Execute<TResult>(string key, Func<T, TResult> func)
        {
            using (T algorithm = new T())
            {
                algorithm.FromXmlString(key);
                return func(algorithm);
            }
        }
        /// <summary>
        /// 按默认规则生成公钥、私钥
        /// </summary>
        /// <param name="publicKey">公钥(Xml格式)</param>
        /// <param name="privateKey">私钥(Xml格式)</param>
        public static void Create(out string publicKey, out string privateKey)
        {
            KeyGenerator.CreateAsymmetricAlgorithmKey<T>(out publicKey, out privateKey);
        }
    }
    public class RSAHelper : AsymmetricAlgorithmHelper<RSACryptoServiceProvider>
    {
        /// <summary>
        /// RSA加密
        /// </summary>
        /// <param name="publickey">公钥</param>
        /// <param name="content">加密前的原始数据</param>
        /// <param name="fOAEP">如果为 true,则使用 OAEP 填充(仅在运行 Microsoft Windows XP 或更高版本的计算机上可用)执行直接的 System.Security.Cryptography.RSA加密;否则,如果为 false,则使用 PKCS#1 1.5 版填充。</param>
        /// <returns>加密后的结果(base64格式)</returns>
        public static string Encrypt(string publickey, string content, bool fOAEP = false)
        {
            return Execute(publickey,
                algorithm => Convert.ToBase64String(algorithm.Encrypt(Encoding.UTF8.GetBytes(content), fOAEP)));
        }
        /// <summary>
        /// RSA解密
        /// </summary>
        /// <param name="privatekey">私钥</param>
        /// <param name="content">加密后的内容(base64格式)</param>
        /// <param name="fOAEP">如果为 true,则使用 OAEP 填充(仅在运行 Microsoft Windows XP 或更高版本的计算机上可用)执行直接的 System.Security.Cryptography.RSA加密;否则,如果为 false,则使用 PKCS#1 1.5 版填充。</param>
        /// <returns></returns>
        public static string Decrypt(string privatekey, string content, bool fOAEP = false)
        {
            return Execute(privatekey,
                algorithm => Encoding.UTF8.GetString(algorithm.Decrypt(Convert.FromBase64String(content), fOAEP)));
        }
        /// <summary>
        /// RSA签名
        /// </summary>
        /// <param name="privatekey">私钥</param>
        /// <param name="content">需签名的原始数据(utf-8)</param>
        /// <param name="halg">签名采用的算法,如果传null,则采用MD5算法</param>
        /// <returns>签名后的值(base64格式)</returns>
        public static string SignData(string privatekey, string content, object halg = null)
        {
            return Execute(privatekey,
                algorithm => Convert.ToBase64String(algorithm.SignData(Encoding.UTF8.GetBytes(content), GetHalg(halg))));
        }
        /// <summary>
        /// RSA验签
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="content">需验证签名的数据(utf-8)</param>
        /// <param name="signature">需验证的签名字符串(base64格式)</param>
        /// <param name="halg">签名采用的算法,如果传null,则采用MD5算法</param>
        /// <returns></returns>
        public static bool VerifyData(string publicKey, string content, string signature, object halg = null)
        {
            return Execute(publicKey,
                algorithm => algorithm.VerifyData(Encoding.UTF8.GetBytes(content), GetHalg(halg), Convert.FromBase64String(signature)));
        }
        private static object GetHalg(object halg)
        {
            if (halg == null)
            {
                halg = "MD5";
            }
            return halg;
        }
        /// <summary>
        /// 生成公钥、私钥
        /// </summary>
        /// <param name="publicKey">公钥(Xml格式)</param>
        /// <param name="privateKey">私钥(Xml格式)</param>
        /// <param name="keySize">要生成的KeySize,支持的MinSize:384 MaxSize:16384 SkipSize:8</param>
        public static void Create(out string publicKey, out string privateKey, int keySize = 1024)
        {
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider(keySize);
            KeyGenerator.CreateAsymmetricAlgorithmKey(out publicKey, out privateKey, provider);
        }
    } 
    public class DSAHelper : AsymmetricAlgorithmHelper<DSACryptoServiceProvider>
    {
        /// <summary>
        /// DSA签名
        /// </summary>
        /// <param name="privatekey">私钥</param>
        /// <param name="content">需签名的原始数据(utf-8)</param>
        /// <returns>签名后的值(base64格式)</returns>
        public static string SignData(string privatekey, string content)
        {
            return Execute(privatekey,
                algorithm => Convert.ToBase64String(algorithm.SignData(Encoding.UTF8.GetBytes(content))));
        }
        /// <summary>
        /// DSA验签
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="content">需验证签名的数据(utf-8)</param>
        /// <param name="signature">需验证的签名字符串(base64格式)</param>
        /// <returns></returns>
        public static bool VerifyData(string publicKey, string content, string signature)
        {
            return Execute(publicKey,
                algorithm => algorithm.VerifyData(Encoding.UTF8.GetBytes(content), Convert.FromBase64String(signature)));
        }
        /// <summary>
        /// 生成公钥、私钥
        /// </summary>
        /// <param name="publicKey">公钥(Xml格式)</param>
        /// <param name="privateKey">私钥(Xml格式)</param>
        /// <param name="keySize">要生成的KeySize,支持的MinSize:512 MaxSize:1024 SkipSize:64</param>
        public static void Create(out string publicKey, out string privateKey, int keySize = 1024)
        {
            DSACryptoServiceProvider provider = new DSACryptoServiceProvider(keySize);
            KeyGenerator.CreateAsymmetricAlgorithmKey(out publicKey, out privateKey, provider);
        }
    }
C#下的测试代码,RSAConverter的代码地址为 http://blog.csdn.net/starfd/article/details/51838589
        static void RSADemo()
        {
            string publicJavaKey, privateJavaKey, content, publicCSharpKey, privateCSharpKey, signData;
            //java的base64格式秘钥
            privateJavaKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMsNFZUmKwtwFH271JMbjuMslL2C4Dw5iYps/jkXu5vxhYzNaKMA5Bu2Adlhw2FzA/fapglWDN68/8OG1veX0M9C/5YhigsIdhzixi6WrkMFfqp/nZhcRgcm900P0UM1wAceemPEvU7+uq9bSrMJWxwSmcryP63KKtCZcFfW05u9AgMBAAECgYBIiisctp8IHglkBddimqTIaePVdE0RluiZKGkGEoF2q6kvbS6llSro73PnqjJ3vPQ89sL8cN52MIUa4DAqEfWJgtl/cy2RKK64ajESZadIQnW2F2Whsuob/T1wEv05jQeej4qUdVp5yz1lhWvwlwoB3BLWPwhnReg87OS8jFFQLQJBAPEA0kv1OIhlQx1ew1WEqd8mK2VbtmLDOwZL4uZvDkx7/dtthVxNw25cVfJM6V9AET2j9Jbyt2pHibfjf1fICmMCQQDXr6+yfl7yLOVDiM4lQFH7if03GsJsfvizvUyoI6suumyTFhjfkDyL3JM4flyWDpFPN76b9TDpjaz4pY1KfItfAkBG0ZD6VRLJscfpB4GqzZMFSbgSzsJnfysHDKGeSSAQhZbxNdusZgV5lpSC4Orq3G60iEtFWAlhp6fma2luKBA1AkEArS3OR+Y5u/+aUcBtrPFZIjvoia89vrmwXTk4bKS/FPTwqqUKca8xPidsOecT1hR6Tf33WOflTxHHeZoLuWwIxwJAZQ4fS9Gatxyn+3ubXxltbyKxpYhfwEP1JvIQqOACtKLXBjWoYzdnUO2jr6WZ2UBeaDCqzA30VGmjG7pud94ZhA==";
            publicJavaKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLDRWVJisLcBR9u9STG47jLJS9guA8OYmKbP45F7ub8YWMzWijAOQbtgHZYcNhcwP32qYJVgzevP/Dhtb3l9DPQv+WIYoLCHYc4sYulq5DBX6qf52YXEYHJvdND9FDNcAHHnpjxL1O/rqvW0qzCVscEpnK8j+tyirQmXBX1tObvQIDAQAB";
            content = "测试数据你好";
            //转成C#的xml格式
            publicCSharpKey = RSAConverter.RSAPublicKeyJava2DotNet(publicJavaKey);
            privateCSharpKey = RSAConverter.RSAPrivateKeyJava2DotNet(privateJavaKey);
            Console.WriteLine("转换得到的C#公钥:" + publicCSharpKey);
            Console.WriteLine("转换得到的C#私钥:" + privateCSharpKey);

            //RSAHelper.Create(out publicCSharpKey, out privateCSharpKey, 1024);
            string encData = RSAHelper.Encrypt(publicCSharpKey, content);
            Console.WriteLine("公钥加密结果:" + encData);
            Console.WriteLine("私钥解密结果:" + RSAHelper.Decrypt(privateCSharpKey, encData));
            //下面是java通过SHA1WithRSA生成的签名
            //Dv67xT5SgGQ9q+bKVWuyyxljx28cxNkIMDk5ro8cMopsiPf7Z8/n/02yaN/SVUQPmWJk/f+cjwydikVStwjkll49/D4PrTW+nd4XWr5hea8n7c6JTdRvaOGwFG3Do1n8Sndj7aqxuUWUmlLiC1dYEHeZhSwm9BCMJJSvF8n34CY=
            //下面是JAVA通过MD5withRSA生成的签名
            //MUXPVxxNZOlzDY03hOXQgQLQnJ/SrJa0lxQAx8Kl+H+pLBcL6cqdLupVwK6mwKZ1mRP2CCwGaQC8wHkOVRafPdkOSRsnKnkAjRv1iqHBxJtPCG83XlrB7AofzqHi/VULCA9KdWqmvnarVCV+lVwwUVCXP5cK1nwEJN258T/eV8M=
            //下面是JAVA通过SHA256WithRSA生成的签名
            //qPfkIAITcKW452/NacSQHjNbBUtJNhel4SpTMp1T/nGaY0Z4I3Xx13/aVl001ZKwBfdFf7cIPAKlbqmywm3sqEzVpBQlVOYMZBARlHAoOexTCZk50tgrCFUlXXa2pWt+jRS2lGUX5esbo6cKS0Yk1fdkYlm+4S4NRKYgEAXO+lY=
            string halg = "SHA256";//SHA1 MD5 SHA256
            signData = RSAHelper.SignData(privateCSharpKey, content, halg);//SHA1
            Console.WriteLine("生成签名:" + signData);
            Console.WriteLine("签名一致:" + RSAHelper.VerifyData(publicCSharpKey, content, signData, halg));
        }
        static void DSADemo()
        {
            string publicKey, privateKey;
            DSAHelper.Create(out publicKey, out privateKey);
            string content = "测试数据";
            string signData = DSAHelper.SignData(privateKey, content);
            Console.WriteLine("生成签名:" + signData);
            Console.WriteLine("签名一致:" + DSAHelper.VerifyData(publicKey, content, signData));
        }

然后是JAVA版的代码,注意与参考地址代码基本相同,只是调整了Hash算法传递,同时包含了测试代码
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

public class Test {

	private static String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMsNFZUmKwtwFH271JMbjuMslL2C4Dw5iYps/jkXu5vxhYzNaKMA5Bu2Adlhw2FzA/fapglWDN68/8OG1veX0M9C/5YhigsIdhzixi6WrkMFfqp/nZhcRgcm900P0UM1wAceemPEvU7+uq9bSrMJWxwSmcryP63KKtCZcFfW05u9AgMBAAECgYBIiisctp8IHglkBddimqTIaePVdE0RluiZKGkGEoF2q6kvbS6llSro73PnqjJ3vPQ89sL8cN52MIUa4DAqEfWJgtl/cy2RKK64ajESZadIQnW2F2Whsuob/T1wEv05jQeej4qUdVp5yz1lhWvwlwoB3BLWPwhnReg87OS8jFFQLQJBAPEA0kv1OIhlQx1ew1WEqd8mK2VbtmLDOwZL4uZvDkx7/dtthVxNw25cVfJM6V9AET2j9Jbyt2pHibfjf1fICmMCQQDXr6+yfl7yLOVDiM4lQFH7if03GsJsfvizvUyoI6suumyTFhjfkDyL3JM4flyWDpFPN76b9TDpjaz4pY1KfItfAkBG0ZD6VRLJscfpB4GqzZMFSbgSzsJnfysHDKGeSSAQhZbxNdusZgV5lpSC4Orq3G60iEtFWAlhp6fma2luKBA1AkEArS3OR+Y5u/+aUcBtrPFZIjvoia89vrmwXTk4bKS/FPTwqqUKca8xPidsOecT1hR6Tf33WOflTxHHeZoLuWwIxwJAZQ4fS9Gatxyn+3ubXxltbyKxpYhfwEP1JvIQqOACtKLXBjWoYzdnUO2jr6WZ2UBeaDCqzA30VGmjG7pud94ZhA==";
	private static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLDRWVJisLcBR9u9STG47jLJS9guA8OYmKbP45F7ub8YWMzWijAOQbtgHZYcNhcwP32qYJVgzevP/Dhtb3l9DPQv+WIYoLCHYc4sYulq5DBX6qf52YXEYHJvdND9FDNcAHHnpjxL1O/rqvW0qzCVscEpnK8j+tyirQmXBX1tObvQIDAQAB";
	private static String algorithm="SHA256WithRSA";//MD5withRSA  SHA1WithRSA SHA256WithRSA
	
	public static void main(String[] args) {
		Test run1 = new Test();
		try {
			String sign = run1.rsaSign("测试数据你好", privateKey, "utf-8", algorithm);
			System.out.println(sign);
			boolean bRet = run1.doCheck("测试数据你好", sign, publicKey, "utf-8", algorithm);
			System.out.println(bRet);
		} catch (SignatureException e) {
			e.printStackTrace();
		}
	}

	public String rsaSign(String content, String privateKey, String charset, String algorithm) throws SignatureException {
		try {
			PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));

			Signature signature = Signature.getInstance(algorithm);//MD5withRSA  SHA1WithRSA SHA256WithRSA
			signature.initSign(priKey);
			if (StringUtils.isEmpty(charset)) {
				signature.update(content.getBytes());
			} else {
				signature.update(content.getBytes(charset));
			}
			byte[] signed = signature.sign();
			return new String(Base64.encodeBase64(signed));
		} catch (Exception e) {
			throw new SignatureException("RSAcontent = " + content + "; charset = " + charset, e);
		}
	}

	boolean doCheck(String content, String sign, String publicKey, String charset, String algorithm) throws SignatureException {
		try {
			PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));

			Signature signature = Signature.getInstance(algorithm);//MD5withRSA  SHA1WithRSA SHA256WithRSA
			signature.initVerify(pubKey);
			byte[] encodedKey = content.getBytes(charset);
			signature.update(encodedKey);
			// signature.update(getContentBytes(content, charset));
			return signature.verify(Base64.decodeBase64(sign.getBytes()));
		} catch (Exception e) {
			throw new SignatureException(
					"RSA验证签名[content = " + content + "; charset = " + charset + "; signature = " + sign + "]发生异常!", e);
		}
	}

	private PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws NoSuchAlgorithmException {
		try {
			KeyFactory keyFactory = KeyFactory.getInstance(algorithm);

			StringWriter writer = new StringWriter();
			// StreamUtil.io(new InputStreamReader(ins), writer);
			// byte[] encodedKey = writer.toString().getBytes();
			byte[] encodedKey = IOUtils.toByteArray(ins);
			// 先base64解码
			encodedKey = Base64.decodeBase64(encodedKey);
			return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
		} catch (IOException ex) {
			// 不可能发生
		} catch (InvalidKeySpecException ex) {
			// 不可能发生
		}
		return null;
	}

	public PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
		if (ins == null || StringUtils.isEmpty(algorithm)) {
			return null;
		}

		KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
		byte[] encodedKey = IOUtils.toByteArray(ins);

		encodedKey = Base64.decodeBase64(encodedKey);
		return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
	}
}

查看评论

使用RSA、MD5对参数生成签名与验签

在日常的工作中,我们对外提供的接口或调用三方的接口往往有一步生成签名或验签的步骤,这个步骤主要是验证调用方是不是合法的以及内容是否被修改。比如:对于某些网上公开下载的软件,视频,尤其是镜像文件。如果被...
  • Mr_Smile2014
  • Mr_Smile2014
  • 2016-08-05 16:55:33
  • 15464

SHA256withRSA签名验签 & BASE64加解密

//SHA256withRSA签名验签 //BASE64加解密
  • u010071621
  • u010071621
  • 2017-01-23 11:07:24
  • 10625

支付宝RSA签名验签工具

  • 2017年08月31日 14:12
  • 16.92MB
  • 下载

RSA加密签名验签工具

  • 2017年02月20日 17:31
  • 16.92MB
  • 下载

RSA签名和验签过程

1.签名过程: client提取消息m的消息摘要h(m),并使用自己的私钥对摘要h(m)进行加密,生成签名s。client将签名s和消息m一起,使用server发过来的公钥进行加密,获得密文c,发...
  • zju_bigjar
  • zju_bigjar
  • 2016-04-28 09:07:36
  • 6356

写一个RSA签名与验签的Demo

一、RSA私钥及公钥生成 OpenSSL工具安装 RSA私钥及公钥生成 OpenSSL工具安装 Linux用户(以Ubuntu为例) sudo apt-get install o...
  • jinchaoh
  • jinchaoh
  • 2015-12-28 15:07:07
  • 3389

支付宝RSA加密签名验签工具

  • 2017年07月27日 21:27
  • 28.24MB
  • 下载

RSA算法工具(数字签名等)

  • 2015年09月14日 11:26
  • 1.57MB
  • 下载

RSA加密与SHA签名用法详解

基础知识 什么是RSA? 答:RSA是一种非对称加密算法,常用来对传输数据进行加密, 配合上数字摘要算法,也可以进行文字签名。 2.RSA加密中padding? 答:pa...
  • Levilly
  • Levilly
  • 2016-06-29 23:11:24
  • 3793

SHA256withRSA签名验签(JAVA实现,RSA密钥对)

SHA256withRSA签名验签
  • Learning_LB
  • Learning_LB
  • 2017-08-07 19:48:09
  • 6211
    个人资料
    持之以恒
    等级:
    访问量: 40万+
    积分: 4302
    排名: 8758
    最新评论