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

原创 2016年07月15日 15:44:56

重要的事情说三遍,该篇文章主要是验证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));
	}
}

版权声明:本文为starfd原创文章,未经博主允许不得转载。

相关文章推荐

Java使用RSA加密解密签名及校验

由于项目要用到非对称加密解密签名校验什么的,于是参考《Java加密解密的艺术》写一个RSA进行加密解密签名及校验的Demo,代码很简单,特此分享!RSA加密解密类:package com.ihep; ...

RSA签名和验签过程

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

SHA1WithRSA签名使用openssl 实现

引言: 2017年就要到了,想想自己使用阿里云搭的博客 眼看就要到期了。 虽说没写几遍有质量的文章吧,但是放其不管也于心不忍。这几天就琢磨着把几遍有内容的转到博客中。在寻求着落点的时候发现M...
  • vr7jj
  • vr7jj
  • 2016-12-12 21:07
  • 2041

sha1withRSA md5withRSA分析

sha1withRSA哈希算法分析 查资料:http://stackoverflow.com/questions/7646259/can-any-one-tell-what-i2d-x509-sig-...

开发支付宝支付用DELPHI实现 RSA签名

近来根据业务需求 在ERP中集成了微信支付,支付宝支付,开发支付宝支付时最大的障碍就是RSA签名,找了很多资料,最终用 下了个libeay32.pas  根据网上资料最终解决了问题 funct...

SHA1WithRSA 验证数字签名

public class SignProvider {    private SignProvider() {    }    /...

基于私钥加密公钥解密的RSA算法C#实现

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。 RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一...

C#下RSA算法的实现(适用于支付宝和易宝支付)

RSA算法代码: using System; using System.Collections.Generic; using System.Text; using System.IO; using S...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)