iOS,Android,WP, .NET通用AES加密算法
这两天为移动App开发API,结果实现加密验证时碰到一大坑。这里不得不吐槽下又臭又硬的iOS,Windows Server无法解密出正确的结果,Android则可以,后来使用了通用的AES256加密算法才最终搞定。
搞服务器端小伙伴没有接触过iOS,所以也没料到过这种情形。他使用了AES128 with IV的加密算法,Android端可以顺利通过加密验证。
但是iOS端使用AES128算法后出现问题,虽然可以在本地加密解密,但是无法被服务器解密成功。
后来经过多方查找,才了解到一个蛋疼的事实,iOS只支持AES PKCS7Padding算法,在服务器端修改为相应算法后,顺利通过。
这里主要参考一篇博文,以下给出通用AES算法:
Objective-C:
//头文件
#import <Foundation/Foundation.h> @interface NSData (AES)
- (NSData *)AES256EncryptWithKey:(NSString *)key;
- (NSData *)AES256DecryptWithKey:(NSString *)key;
@end
实现代码:
#import "NSData+AES256.h"
#import <CommonCrypto/CommonCryptor.h> @implementation NSData (AES) -(NSData *)AES256EncryptWithKey:(NSString *)key {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) // fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; //See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize); size_t numBytesEncrypted = ;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
} free(buffer); //free the buffer;
return nil;} -(NSData *)AES256DecryptWithKey:(NSString *)key {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) // fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; //See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize); size_t numBytesDecrypted = ;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted); if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
} free(buffer); //free the buffer;
return nil;
}
@end
C#:
#region
/// <summary>
/// 256位AES加密
/// </summary>
/// <param name="toEncrypt"></param>
/// <returns></returns>
public static string Encrypt(string toEncrypt)
{
// 256-AES key
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, , toEncryptArray.Length);
return Convert.ToBase64String(resultArray, , resultArray.Length);
}
/// <summary>
/// 256位AES解密
/// </summary>
/// <param name="toDecrypt"></param>
/// <returns></returns>
public static string Decrypt(string toDecrypt)
{
// 256-AES key
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, , toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
#endregion
Java:
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import android.util.Base64; public class AESUtils {
/**
* 加密
* @param content 需要加密的内容
* @param password 加密密码
* @return
*/
private static String Key="key"; public static String encode(String stringToEncode) throws NullPointerException { try {
SecretKeySpec skeySpec = getKey(Key);
byte[] clearText = stringToEncode.getBytes("UTF8");
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
String encrypedValue = Base64.encodeToString(cipher.doFinal(clearText), Base64.DEFAULT);
return encrypedValue; } catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return "";
} private static SecretKeySpec getKey(String password) throws UnsupportedEncodingException {
int keyLength = 256;
byte[] keyBytes = new byte[keyLength / 8];
Arrays.fill(keyBytes, (byte) 0x0);
byte[] passwordBytes = password.getBytes("UTF-8");
int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length;
System.arraycopy(passwordBytes, 0, keyBytes, 0, length);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
return key;
} }
Windows Phone&Windows Store:
public static string Encrypt(string toEncrypt)
{ //创建算法提供器
var symmetricAlgorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
//key处理
IBuffer tempKey = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);
CryptographicKey cryptKey = symmetricAlgorithm.CreateSymmetricKey(tempKey);
// 将需要加密的数据转换为 IBuffer 类型
var dateBuffer = CryptographicBuffer.ConvertStringToBinary(toEncrypt, BinaryStringEncoding.Utf8); try
{
// 加密数据
var encrypted = CryptographicEngine.Encrypt(cryptKey,dateBuffer,null);
// Debug.WriteLine(encrypted);
return CryptographicBuffer.EncodeToBase64String(encrypted);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
} return null;
}
iOS,Android,WP, .NET通用AES加密算法的更多相关文章
- iOS,Android,.NET通用AES加密算法
原文:iOS,Android,.NET通用AES加密算法 这两天为移动App开发API,结果实现加密验证时碰到一大坑.这里不得不吐槽下又臭又硬的iOS,Windows Server无法解密出正确的结果 ...
- Emoji表情符号兼容方案(适用ios,android,wp等平台)
http://blog.csdn.net/qdkfriend/article/details/7576524 Emoji表情符号兼容方案 一 什么是Emoji emoji就是表情符号:词义来自日语(え ...
- 编程之路-client学习知识点纲要(Web/iOS/Android/WP)
Advanced:高级内容 Architect:架构设计 Core:框架底层原理分析 Language:框架经常使用语言 Objective-C Dart Swift Java Network:网络 ...
- PHP android ios相互兼容的AES加密算法
APP项目用户密码传输一直没有用HTTPS,考虑到用户的隐私暂时先用AES对密码加密,以后也可以用于手机端与服务端加密交互. PHP的免费版phpAES项目,手机端解码各种不对. 好不容易找了PHP ...
- 【转】PHP android ios相互兼容的AES加密算法
APP项目用户密码传输一直没有用HTTPS,考虑到用户的隐私暂时先用AES对密码加密,以后也可以用于手机端与服务端加密交互. PHP的免费版phpAES项目,手机端解码各种不对. 好不容易找了PHP ...
- 毫无保留开源我写的:IOS Android Ipad 多点触摸通用js 库
毫无保留开源我写的:IOS Android Ipad 多点触摸通用js 库 在线演示地址: http://m.yunxunmi.com/ 支持 IOS Android Ipad 等不同操作系统的手持或 ...
- Android AES加密算法及事实上现
昨天老大叫我看看android加密算法.于是网上找了找,找到了AES加密算法.(当然还有MD5,BASE64什么的http://snowolf.iteye.com/blog/379860这篇文章列举了 ...
- C#/IOS/Android通用加密解密方法
原文:C#/IOS/Android通用加密解密方法 公司在做移动端ios/android,服务器提供接口使用的.net,用到加密解密这一块,也在网上找了一些方法,有些是.net加密了android解密 ...
- Android AES加密算法,现在实际上
昨天,老板让我来看看android加密算法.于是在网上找了找,发现AES加密算法.(当然,MD5,BASE64什么http://snowolf.iteye.com/blog/379860这篇文章列举了 ...
随机推荐
- 使用thymeleaf一旦没有闭合标签就会报错怎么解决
问题:input标签未关闭报bug,代码稍有不慎就出小问题 使用springboot的thymeleaf模板时默认会对HTML进行严格的检查,导致当你的标签没有闭合时就会通不过,例如: //要想通过, ...
- sqlserver的substring详细用法
SQL 中的 substring 函数是用来截取一个栏位资料中的其中一部分. 例如,我们需要将字符串'abdcsef'中的‘abd’给提取出来,则可用substring 来实现: select sub ...
- JS页面跳转大全
所谓的js页面跳转就是利用javesrcipt对打开的页面ULR进行跳转,如我们打开的是A页面,通过javsrcipt脚本就会跳转到B页面.目前很多垃圾站经常用js跳转将正常页面跳转到广告页面,当然也 ...
- 2018.12.08 codeforces 946D. Timetable(背包)
传送门 题意简述:有一个人上n天课,每天有m个小时的时间安排表(一个01串),为1表示要上课,否则不上课,求出如果可以最多翘kkk节课这nnn天在校待的总时间的最小值(一天必须在所有课上完后才能离开) ...
- 2018.11.14 uoj#34. 多项式乘法(fft)
传送门 NOIpNOIpNOIp爆炸不能阻止我搞oioioi的决心 信息技术课进行一点康复训练. fftfftfft板题. 代码: #include<bits/stdc++.h> usin ...
- 添加全局函数$.extend和对象方法$.fn
## $(function () { $.fn.shadow = function (opts) { return this.each(function () { var defaults = { / ...
- 2.1.4synchronized方法与锁对象
为了证明线程锁的是对象 测试 package com.cky.bean; /** * Created by chenkaiyang on 2017/12/4. */ public class MyOb ...
- (转).net面试题(老赵)
转自:http://www.cnblogs.com/chenxiaoran/archive/2012/05/27/2519988.html 1.什么是CLR 公共语言运行时(Comman langua ...
- 基于SVG+AJAX的网页数据监控
这个是前一阵做的一个火灾报警主机数据网页监控,前后台主要耗时5小时.绘图2小时,配置后端采集端1小时,测试2小时. 用的SVG,上面画的指示灯可以实时显示传感器的状态. 用开源方案实现. 如果集成到自 ...
- 当Windows Phone遇到Windows 8
三年前,Windows Phone系统的发布表示了微软夺回移动市场的决心.一年前,Windows 8的发布,昭示着Windows Phone系统取得的成功——扁平化图标风格.动态磁贴.SkyDrive ...