您的位置:首页 > 其它

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

2016-07-15 15:44 369 查看
重要的事情说三遍,该篇文章主要是验证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));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: