公司在做移動端iOS/Android,服務器提供接口使用的.net,用到加密解密這一塊,也在網上找了一些方法,有些是.net加密了Android解密不了,或者反之。下面的是三個平台都可以加密解密的方法。加密解密中用到的key="1234578";在調取方法時傳值即可。
C#代碼
#region 跨平台加解密(c#)
/// <summary>
/// 對字符串進行DES加密
/// </summary>
/// <param name="sourceString">待加密的字符串</param>
/// <returns>加密後的BASE64編碼的字符串</returns>
public string Encrypt(string sourceString, string sKey)
{
byte[] btKey = Encoding.UTF8.GetBytes(sKey);
byte[] btIV = Encoding.UTF8.GetBytes(sKey);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
using (MemoryStream ms = new MemoryStream())
{
byte[] inData = Encoding.UTF8.GetBytes(sourceString);
try
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
{
cs.Write(inData, 0, inData.Length);
cs.FlushFinalBlock();
}
return Convert.ToBase64String(ms.ToArray());
}
catch
{
throw;
}
}
}
/// <summary>
/// 解密
/// </summary>
/// <param name="pToDecrypt">要解密的以Base64</param>
/// <param name="sKey">密鑰,且必須為8位</param>
/// <returns>已解密的字符串</returns>
public string Decrypt(string pToDecrypt, string sKey)
{
//轉義特殊字符
pToDecrypt = pToDecrypt.Replace("-", "+");
pToDecrypt = pToDecrypt.Replace("_", "/");
pToDecrypt = pToDecrypt.Replace("~", "=");
byte[] inputByteArray = Convert.FromBase64String(pToDecrypt);
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
cs.Close();
}
string str = Encoding.UTF8.GetString(ms.ToArray());
ms.Close();
return str;
}
}
#endregion
IOS代碼
static const char* encryptWithKeyAndType(const char *text,CCOperation encryptOperation,char *key)
{
NSString *textString=[[NSString alloc]initWithCString:text encoding:NSUTF8StringEncoding];
// NSLog(@"[[item.url description] UTF8String=%@",textString);
const void *dataIn;
size_t dataInLength;
if (encryptOperation == kCCDecrypt)//傳遞decrypt 解碼
{
//解碼 base64
NSData *decryptData = [GTMBase64 decodeData:[textString dataUsingEncoding:NSUTF8StringEncoding]];//轉utf-8並decode
dataInLength = [decryptData length];
dataIn = [decryptData bytes];
}
else //encrypt
{
NSData* encryptData = [textString dataUsingEncoding:NSUTF8StringEncoding];
dataInLength = [encryptData length];
dataIn = (const void *)[encryptData bytes];
}
CCCryptorStatus ccStatus;
uint8_t *dataOut = NULL; //理解位type/typedef 縮寫(效維護代碼比:用int用long用typedef定義)
size_t dataOutAvailable = 0; //size_t 操作符sizeof返結類型
size_t dataOutMoved = 0;
dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
memset((void *)dataOut, 00, dataOutAvailable);//已辟內存空間buffer首 1 字節值設值 0
//NSString *initIv = @"12345678";
const void *vkey = key;
const void *iv = (const void *) key; //[initIv UTF8String];
//CCCrypt函數 加密/解密
ccStatus = CCCrypt(encryptOperation,// 加密/解密
kCCAlgorithmDES,// 加密根據哪標准(des3desaes)
kCCOptionPKCS7Padding,// 選項組密碼算(des:每塊組加密 3DES:每塊組加三同密)
vkey, //密鑰 加密解密密鑰必須致
kCCKeySizeDES,// DES 密鑰(kCCKeySizeDES=8)
iv, // 選初始矢量
dataIn, // 數據存儲單元
dataInLength,// 數據
(void *)dataOut,// 用於返數據
dataOutAvailable,
&dataOutMoved);
NSString *result = nil;
if (encryptOperation == kCCDecrypt)//encryptOperation==1 解碼
{
//解密data數據改變utf-8字符串
result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved] encoding:NSUTF8StringEncoding];
}
else //encryptOperation==0 (加密程加密數據轉base64)
{
//編碼 base64
NSData *data = [NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved];
result = [GTMBase64 stringByEncodingData:data];
}
return [result UTF8String];
}
+(NSString*)encryptWithContent:(NSString*)content type:(CCOperation)type key:(NSString*)aKey
{
const char * contentChar =[content UTF8String];
char * keyChar =(char*)[aKey UTF8String];
const char *miChar;
miChar = encryptWithKeyAndType(contentChar, type, keyChar);
return [NSString stringWithCString:miChar encoding:NSUTF8StringEncoding];
}
Android代碼
//加密
public static String DecryptDoNet(String message, String key)
throws Exception {
byte[] bytesrc = Base64.decode(message.getBytes(), Base64.DEFAULT);
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] retByte = cipher.doFinal(bytesrc);
return new String(retByte);
}
// 解密
public static String EncryptAsDoNet(String message, String key)
throws Exception {
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] encryptbyte = cipher.doFinal(message.getBytes());
return new String(Base64.encode(encryptbyte, Base64.DEFAULT));
}
最後還要注意一下,一般在客戶端調用接口時,請求的是URL地址,參數需要加密,比如token,如果token裡含有+號,URL會轉碼為空格,這時在.net端接收到token時,需要把token中的空格替換為+號:token = Regex.Replace(token, @"\s", "+");這樣接收到的token才能正常的解密。