记得去年上半年做了个AES和RSA加密解密的功能,最近又回到了这里。不同的是,今年这同事开始的时候给我的不是cer证书,而是Base64,或者16进制的modules和exponent,然后有点束手无策。[C# Java间进行RSA加密解密交互](http://blog.csdn.net/road2010/article/details/40071843) 后来在网上找到篇文章,参照它的这个方法,是能解,但是我这android手机端,字符串“demon”解出来之后的字符长度一直是76,而c#服务端一直是128。
后来同事找帮忙,生成了一对cer公私密钥证书,然而问题又来了,C#加密解密的长度是344,我这边还是76.不知道是否广大的网友能否帮我解答一下。
现在我将以前写的c#端和android端的RSA和AES加密解密的贴出来,望对大家有所裨益,也算做个记录。
C#
RSA:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace CloudLearn.Tool.Security
{
public static class RSA
{
private static string CERT = “Theoservice”;
private static int KEYLENGTH = 256;
private static int BLOCKSIZE = KEYLENGTH - 11;
static RSA()
{
CERT = SecuritySection.Default.Name;
KEYLENGTH = SecuritySection.Default.Length;
BLOCKSIZE = KEYLENGTH - 11;
}
private static X509Certificate2 GetRSACertificate()
{
X509Certificate2 clientCert = null;
if (clientCert == null)
{
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (var certificate in store.Certificates)
{
if (certificate.GetNameInfo(X509NameType.SimpleName, false) == CERT)
{
clientCert = certificate;
break;
}
}
}
return clientCert;
}
public static RSACryptoServiceProvider GetPrivateKey()
{
var clientCert = GetRSACertificate();
var publicKey = (RSACryptoServiceProvider)clientCert.PrivateKey;
return publicKey;
}
public static string Encrypt(string rawText)
{
return Encrypt(rawText, GetPrivateKey());
}
///
/// RSA加密
///
///
///
///
public static string Encrypt(string rawText, RSACryptoServiceProvider rsa)
{
byte[] cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(rawText), false);
return Convert.ToBase64String(cipherbytes);
}
public static string Decrypt(string rawText)
{
return Decrypt(rawText, GetPrivateKey());
}
///
/// RSA解密
///
///
///
///
public static string Decrypt(string rawText, RSACryptoServiceProvider rsa)
{
try
{
var encryptedBytes = Convert.FromBase64String(rawText);
int numBlock = encryptedBytes.Length / KEYLENGTH;
byte[] rawResult = new byte[0];
var buffer = new byte[KEYLENGTH];
//var buffer1 = rsa.Decrypt(encryptedBytes, false);
for (var i = 0; i < numBlock; i++)
{
Array.Copy(encryptedBytes, i * KEYLENGTH, buffer, 0, buffer.Length);
var decryptedBytes = rsa.Decrypt(buffer, false);
var resultBuffer = new byte[rawResult.Length + decryptedBytes.Length];
Array.Copy(rawResult, resultBuffer, rawResult.Length);
Array.Copy(decryptedBytes, 0, resultBuffer, rawResult.Length, decryptedBytes.Length);
rawResult = resultBuffer;
}
return Encoding.UTF8.GetString(rawResult); ;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
}
}
AES:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace CloudLearn.Tool.Security
{
public static class AES
{
public static int Length { get; set; }
static AES()
{
Length = SecuritySection.Default.AESKeyLength;
}
///
/// 有密码的AES加密
///
/// 加密字符
/// 加密的密码
/// 密钥
///
public static string Encrypt(string rawText, string key)
{
byte[] keyArray = Encoding.UTF8.GetBytes(key);//61 97
byte[] toEncryptArray = Encoding.UTF8.GetBytes(rawText);
RijndaelManaged rDel = new RijndaelManaged();
//rDel.BlockSize = 512;
rDel.KeySize = Length * 8;
byte[] iv = new byte[Length];
for (int i = 0; i < Length; i++)
{
iv[i] = 0;
}
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
///
/// AES解密
///
///
///
///
///
public static string Decrypt(string rawText, string key)
{
byte[] keyArray = Encoding.UTF8.GetBytes(key);
byte[] toEncryptArray = Convert.FromBase64String(rawText);
RijndaelManaged rDel = new RijndaelManaged();
rDel.KeySize = Length * 8;
byte[] iv = new byte[Length];
for (int i = 0; i < Length; i++)
{
iv[i] = 0;
}
rDel.IV = iv;
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Encoding.UTF8.GetString(resultArray);
}
}
}
android
RSA
import android.annotation.SuppressLint;
import android.util.Base64;
import android.util.Log;
import com.hbyx.tool.config.Configuration;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPublicKey;
import javax.crypto.Cipher;
public class RSA {
private static Certificate cert;
private static int key_len;
private static Certificate getCert() throws CertificateException {
if (cert == null) {
//Configuration.def.getSecretRsaCer()
//cer证书名称,我是放在RSA加密的同一个包里
cert = CertificateFactory.getInstance("X.509").generateCertificate(
RSA.class.getResourceAsStream(Configuration.def
.getSecretRsaCer()));
key_len = ((RSAPublicKey) cert.getPublicKey()).getModulus()
.bitLength() / 16;
}
return cert;
}
private static String[] splitString(String string, int len) {
// string.split(regularExpression)
int x = string.length() / len;
int y = string.length() % len;
int z = 0;
if (y != 0) {
z = 1;
}
String[] strings = new String[x + z];
String str = "";
for (int i = 0; i < strings.length; i++) {
if (i == x + z - 1 && y != 0) {
str = string.substring(i * len, i * len + y);
} else {
str = string.substring(i * len, i * len + len);
}
strings[i] = str;
}
return strings;
}
@SuppressLint("TrulyRandom")
public static String Encrypt(String str) throws Exception {
byte[] dat = new byte[1024 * 20];
int length = 0;
try {
Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsa.init(Cipher.ENCRYPT_MODE, getCert());
// 加密数据长度 <= 模长-11
String[] datas = splitString(str, key_len - 11);
// 如果明文长度大于模长-11则要分组加密
for (String s : datas) {
for (Byte b : rsa.doFinal(s.getBytes())) {
dat[length++] = b;
}
}
return Base64.encodeToString(dat, 0, length, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
Log.e("RSA.Encrypt", e.getMessage());
throw e;
}
}
}
AES:
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESCipher {
/*
* 加密
* @param key
* @param src
* @return
* @throws Exception
*/
public static String encrypt(String key, String src) throws Exception {
key = createKey(key);
byte[] rawKey = getRawKey(key.getBytes());
byte[] result = encrypt(rawKey, src.getBytes());
return toHex(result);
}
/*
* 解密
* @param key
* @param encrypted
* @return
* @throws Exception
*/
public static String decrypt(String key, String encrypted) throws Exception {
key = createKey(key);
byte[] rawKey = getRawKey(key.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
SecureRandom sr = null;
if (android.os.Build.VERSION.SDK_INT >= 17) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(seed);
kgen.init(256, sr); //256 bits or 128 bits,192bits
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] key, byte[] src) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(src);
return encrypted;
}
private static byte[] decrypt(byte[] key, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
public static String createKey(String userId){
String key = "";
for(int i=0;i<16-(userId.length());i++){
key+="0";
}
key+=userId;
return key;
}
}
好了,希望能有好心的网友帮忙回答一下我的问题,RSA加密(“demon”)之后的密文(base64)长度会有多长,能达到344的长度??那手机端发送密文所耗费的流量也太大了吧。。。。。