当前位置: 首页 > 编程日记 > 正文

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 otherwisechar keyPtr[kCCKeySizeAES256+1]; // 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 heresize_t bufferSize = dataLength + kCCBlockSizeAES128;void *buffer = malloc(bufferSize);size_t numBytesEncrypted = 0;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 deallocationreturn [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 otherwisechar keyPtr[kCCKeySizeAES256+1]; // 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 heresize_t bufferSize = dataLength + kCCBlockSizeAES128;void *buffer = malloc(bufferSize);size_t numBytesDecrypted = 0;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 deallocationreturn [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, 0, toEncryptArray.Length);return Convert.ToBase64String(resultArray, 0, 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, 0, 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;}

相关文章:

【Linux】Linux下的硬链接与符号链接

Linux的初学者常常混淆Linux中的硬链接&#xff08;hard link&#xff09;与符号链接&#xff08;symbol link&#xff09;的概念&#xff0c;分不清楚它们的区别。因此&#xff0c;本文将向读者全面介绍硬链接与符号链接&#xff0c;给予读者以全面的认识。 1.Linux下的文件系…

Unity + SQL数据库创建管理玩家排行榜学习教程

Unity SQL Databases Player Management Leaderboards More! Unity SQL数据库玩家管理排行榜更多&#xff01; MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&…

SQL基础学习总结:2(表的创建、删除、更新和名称修改)

表的创建、删除、更新和名称修改 登录MySQL(mysql -u root -p语句) 步骤&#xff1a; 1.首先得先使用mysql -u root -p语句登录数据库&#xff1b; 2.在"Enter password:"后面输入你设置的密码&#xff0c;然后就登录到MySQL可以进行数据库得操作了。 如下图&#…

需要抛出异常的情况

1、调用一个抛出已检查异常的方法。例如FileInputStream构造器。 2、程序运行中发现错误&#xff0c;并且利用throw语句抛出一个已检查异常。 3、程序出现错误。例如a[-1]0会抛出一个ArrayIndexOutOfBoundsException异常。 4、Java虚拟机和运行时库出现的内部错误。 对于可能会…

2022-2028年中国HDPE膜行业市场研究及投资发展分析报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国HDPE膜行业市场行业相关概述、中国HDPE膜行业市场行业运行环境、分析了中国HDPE膜行业市场…

linux+postfix+extmail+dovecot搭建邮件服务器

一、我们可以重新搭建服务器&#xff0c;也可以利用我前面的搭建方法编译安装&#xff0c;地址&#xff1a;http://wangzan18.blog.51cto.com/8021085/1605480&#xff0c;本次我们使用yum的方法来安装httpd和mysql&#xff0c;我的搭建环境还是我们的CentOS6.6 x86-64位mini版…

2009年3月

1、http://www.west-wind.com/Weblog/posts/509108.aspx Client Templating with jQuery http://jtemplates.tpython.com/ jTemplates is a template engine for JavaScript. 2、http://www.cnblogs.com/QLeelulu/archive/2008/11/27/1342722.html jQuery的模板与数据绑定插件…

UE4创建第一人称射击游戏学习教程

Unreal Engine 4: Create Your Own First-Person Shooter MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; |时长:38节课(9h 56m) |大小解压后:6.8 GB 学…

SQL基础学习总结:3(select语句基础算术运算符比较运算符)

select语句基础 列的查询 从表中选取数据时需要使用select语句&#xff0c;通过select语句查询并选取出必要数据的过程称为匹配查询或查询。 语法结构如下&#xff1a; select <列名1>,<列名2>,<列名3>... from <表名>;该select语句包含了select和f…

Linux——Linux概念架构的理解

摘要 Linux kernel成功的两个原因&#xff1a;&#xff08;1&#xff09;灵活的架构设计使得大量的志愿开发者能够很容易加入到开发过程中&#xff1b;&#xff08;2&#xff09;每个子系统&#xff08;尤其是那些需要改进的&#xff09;都具备良好的可扩展性。正是这两个原因使…

2022-2028年中国GPS导航行业投资分析及前景预测报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国GPS导航行业市场行业相关概述、中国GPS导航行业市场行业运行环境、分析了中国GPS导航行业市…

Geohash的精度问题

网上的关于Geohash的精度问题的说明都不够完整&#xff0c;做了一下补充&#xff0c;可以参见本文表格。 具体的计算方法&#xff1a;Latitude的范围是&#xff1a;-90 到 90Longitude的范围&#xff1a;-180 到 180地球参考球体的周长&#xff1a;40075016.68米geohash长度Lat…

在CentOS上把MySQL从5.5升级到5.6

在CentOS上把MySQL从5.5升级到5.6 摘要&#xff1a;本文记录了在CentOS 6.3上&#xff0c;把MySQL从5.5.28升级到5.6.19的过程。 1. 概述 在我做的一个项目中&#xff0c;最近我对生产服务器上的一系列系统软件进行了升级&#xff0c;包括Git、Nginx、MySQL和PHP。这篇文章讲的…

在3ds Max和Vray中创建赛博朋克圣诞老人室内场景

我叫奥马尔萨米罗什迪&#xff0c;建筑师、室内设计师、助理讲师、摄影师和3d艺术家。2019年获得建筑学硕士学位。我曾为多家建筑事务所和顾问工作&#xff0c;甚至建立了自己的建筑工作室。我有很长的大学教学生涯&#xff0c;从2013年开始&#xff1b;我曾在知名大学教授设计…

Java之网络通信框架mina

mina是一个基于java nio的网络通信框架。主要屏蔽了网络通信的一些细节,对Socket进行封装,并且是NIO的一个实现架构,可以帮助我们快速的开发网络通信,常用于游戏的开发、中间件服务端的程序中。Apache的Mina(Multipurpose Infrastructure Networked Applications)是一个网络应用框架,可以帮助用户开发高性能和高扩展性的网络应用程序;它提供了一个抽象的、事件驱动的异步API,使。

GIT常用命令大全

git config --global color.ui true //让git显示颜色//忽略特殊文件//.gitignore文件 # Windows: Thumbs.db*.egg*.egg-infodist//把该文件也提交到git$ git add -f App.class //强制添加被忽略的特殊文件。

SQL基础学习总结:5(HAVING子句的使用ORDER BY排序子句的使用)

为聚合结果指定条件 HAVING子句 HAVING子句可以让我们筛选分组之后的各种数据&#xff0c;其语法结构如下&#xff1a; SELECT <列名1>,<列名2>,<列名3> FROM <表名> GROUP BY <列名1>,<列名2>,<列名3> HAVING <分组结果对应的…

【转】android错误 aapt.exe已停止工作的解决方法

http://www.jb51.net/article/57420.htm 在使用eclipse进行安卓java的编程的时候&#xff0c;有时候我们会遇到这样的问题&#xff1a;那就是无故弹出aapt.exe停止工作的提示&#xff0c;虽然程序不会崩溃&#xff0c;但是这个提示经常弹出很是烦人。今天&#xff0c;小编就来教…

2022-2028年中国FEP薄膜行业市场发展规模及市场分析预测报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国FEP薄膜行业市场行业相关概述、中国FEP薄膜行业市场行业运行环境、分析了中国FEP薄膜行业市…

Android-----View绘制流程以及invalidate()等相关方法分析 .

引自&#xff1a;http://blog.csdn.net/qinjuning/article/details/7110211 前言&#xff1a; 本文是我读《Android内核剖析》第13章----View工作原理总结而成的&#xff0c;在此膜拜下作者 。同时真挚地向渴望了解 Android 框架层的网友&#xff0c;推荐这本书&#xff0c;希望…

实现ASP.NET MVC3 HtmlHelper 的 RadioButtonList 与CheckBoxList 扩展

ASP.NET MVC3也出来有一段时间了&#xff0c;对于没有RadioButtonList 与CheckBoxList的问题&#xff0c;网上也已经有很多解决方案了&#xff0c;可以for循环拼接出来&#xff0c;也可以引用ASP.NET MVC Toolkit&#xff0c;等等方法。其实本没有必要写出来的&#xff0c;不过…

Blender从头到尾创建一个低多边形场景学习教程

Low Poly Landscapes – Blender Bite Sized Course 流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;48.0 KHz 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09;|大小解压后:3.9 GB |时长:6h 0m 从头到尾创造一个低聚…

SQL基础学习总结:6(INSERT语句的相关使用方法)

数据的插入(INSERT语句的使用方法) 我们之前在表的创建部分简单地介绍了一下INSERT语句的功能和使用方法&#xff0c;现在我们再详细讲一下它的用法。 INSERT语句的基本语法 其语法结构如下&#xff1a; INSERT INTO <表名> (列名1,列名2,列名3...)-> VALUES (数据…

JVM安全退出(如何优雅的关闭java服务)

为了保障应用重启过程中异步操作的执行,避免强制退出JVM可能产生的各种问题,我们可以采用关闭钩子、自定义信号的方式,主动的通知JVM退出,并在JVM关闭前,执行应用程序的一些扫尾工作,进一步保证应用程序可以安全的退出。

常用的CSS(收集)

1. 防padding属性改变盒子模型宽度 Css代码 * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } 当前css将固定盒子模型宽度总是以(显示)指定的宽度(width:300px)为准, 并不会受到padding而强制改变和模型宽…

2022-2028年中国EMI膜产业发展态势及市场发展策略报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国EMI膜行业市场行业相关概述、中国EMI膜行业市场行业运行环境、分析了中国EMI膜行业市场行业…

JS报“Uncaught TypeError: undefined is not a function ”异常

最终的原因是&#xff1a;js引用的位置太靠后&#xff0c;导致使用js方法时&#xff0c;js库还没加载。报此异常的可能原因有&#xff1a; 1、函数名写错了&#xff1b; 2、没有引用js文件&#xff1b; 3、定义晚了转载于:https://www.cnblogs.com/finalstar/p/4254632.html

密码学摘要算法之MD5

摘要算法 摘要算法是一种能产生特殊输出格式的算法&#xff0c;这种算法的特点是:无论用户输入什么长度的原始数据&#xff0c;经过计算后输出的密文都是固定长度的&#xff0c;这种算法的原理是根据一定的运算规则对原数据进行某种形式的提取&#xff0c;这种提取就是摘要&…

Revit:从入门到精通学习教程

流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;48.0 KHz 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; |大小:8.07 GB |时长:12h 16m Revit:从开始到专业掌握Revit 你会学到什么 Revit的最新功能 在Revit中创建…

JDBC编程:1(使用JDBC连接数据库)

使用JDBC连接数据库 下载连接MySQL数据库的驱动 这个jar包可以在官网上对照着你的MySQL版本来下载&#xff0c;这里我下载的是最新的8.0.20版本&#xff0c; 这里是8.0.20版本的驱动包&#xff1a;mysql-connector-java-8.0.20.zip 因为CSDN的积分不能设置永久免费&#xff0…