您的位置:首页 > 移动开发 > Android开发

RSA和AES在c#服务端和android客户端之间的加密解密

2015-06-04 10:19 791 查看
记得去年上半年做了个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的长度??那手机端发送密文所耗费的流量也太大了吧。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: