按处理顺序说明:
1. 生成随机数序列字符串函数
生成方法MT19937,初始种子seed,利用C++库方法,生成:
#include <random> //C++ 库头文件引入
NSString * JKJMT19937Seed(uint32_t seed) {
NSLog(@"MT19937Seed种子:%u",seed);
NSMutableArray *ranVlues = [NSMutableArray array];
std::mt19937 rngCPluc2(seed);
for (int i = 0; i < 64; ++i) {//连续生产64个随机数
unsigned long ranValue = rngCPluc2();
NSNumber *rngVal = [NSNumber numberWithUnsignedLong:ranValue];
[ranVlues addObject:rngVal];
}
NSString *ranSeriesStr = [ranVlues componentsJoinedByString:@""];
NSLog(@"随机数值序列拼接字符串key1 = %@",ranSeriesStr);
return ranSeriesStr;
}
2. 对第一部中的随机数序列字符串进行sha256加密,得到64字节的一个数据流函数。
#import <CommonCrypto/CommonCrypto.h>//加密头文件
NSString * sha256String(NSString *inputString) {
const char *str = inputString.UTF8String;
uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(str, (CC_LONG)strlen(str), buffer);
NSMutableString *strM = [NSMutableString string];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[strM appendFormat:@"%02x", buffer[i]];
}
return [strM copy];
}
3. AES-CBC加密解密方法
/*
CCCrypt方法提供了CBC 和 ECB 两种AES加密模式,
如果不传参数,kCCOptionECBMode,则默认即使CBC模式加密。
ECB模式不是一种可靠安全的加密模式,推荐使用CBC模式。
另外也可以通过其他的库或者方法实现GCM等方式的AES加密。在后面的代码块中翻入方法。
*/
NSData *aesCBCEncrypt(NSData *inputData, NSData *keyData, NSData *ivData) {
NSData *key = keyData;
// 准备一个初始化向量(IV),IV 的长度需要与 AES 加密模式匹配
// 在 AES-CBC 模式下,IV 的长度通常为 AES 块大小(16 字节)
NSData *iv = ivData;
// 创建一个用于存储加密后数据的 NSMutableData 对象
NSMutableData *encryptedData = [NSMutableData dataWithLength:inputData.length + kCCBlockSizeAES128];
size_t encryptedDataLength = 0;
// 使用 AES-256 加密(CBC)
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES,
kCCOptionPKCS7Padding,
key.bytes, key.length,
iv.bytes, // 无需传入 IV
inputData.bytes, inputData.length,
encryptedData.mutableBytes, encryptedData.length,
&encryptedDataLength);
if (cryptStatus == kCCSuccess) {
encryptedData.length = encryptedDataLength;
return encryptedData;
} else {
NSLog(@"AES-256 加密失败");
return nil;
}
}
NSData *aesCBCDecrypt(NSData *encryptedData, NSData *keyData, NSData *ivData) {
// 准备一个初始化向量(IV)
// 在 AES-CBC 模式下,IV 的长度通常为 AES 块大小(16 字节)
NSData *iv = ivData;
// 创建一个用于存储解密后数据的 NSMutableData 对象
NSMutableData *decryptedData = [NSMutableData dataWithLength:encryptedData.length];
size_t decryptedDataLength = 0;
// 进行 AES 解密
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES,
kCCOptionPKCS7Padding,
keyData.bytes, keyData.length,
iv.bytes, // 传入 IV
encryptedData.bytes, encryptedData.length,
decryptedData.mutableBytes, decryptedData.length,
&decryptedDataLength);
if (cryptStatus == kCCSuccess) {
decryptedData.length = decryptedDataLength;
return decryptedData;
} else {
NSLog(@"AES 解密失败");
return nil;
}
}
/*
CCCrypt方法提供了CBC 和 ECB 两种AES加密模式,
如果不传参数,kCCOptionECBMode,则默认即使CBC模式加密。
ECB模式不是一种可靠安全的加密模式,推荐使用CBC模式。
另外也可以通过其他的库或者方法实现GCM等方式的AES加密。在后面的代码块中翻入方法。
*/
4. 前三个步骤已经完成了加密的基本算法代码,接下来直接示例实现一个传参加密:
- (NSString *)EncryptStringFromtServiceStartMap:(NSDictionary *)json {
//补充ts字段。
NSMutableDictionary *muJson = [NSMutableDictionary dictionaryWithDictionary:json];
NSTimeInterval tsVal = [[NSDate date] timeIntervalSince1970];
[muJson setObject:[NSNumber numberWithInteger:(NSUInteger)(1000* tsVal)] forKey:@"ts"];
NSString *jsonString = nil;
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:muJson
options:NSJSONWritingPrettyPrinted
error:&error];
[self loadAESKeyAndIVData];//获取key和iv。
//进行AES加密。
NSData *aesData = aesCBCEncrypt(jsonData, self.aesSHA256keyData, self.aesIVData);
//base64再次加密AES-CBC加密后的数据流,返回值作为start_service的参数
NSString *base64 = [aesData base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0];
NSString *encryptStr = base64;
NSLog(@"jsonContent:%@",muJson);
NSLog(@"start_service参数encryptStr = %@",encryptStr);
NSData *uncodeAESData = aesCBCDecrypt(aesData, self.aesSHA256keyData, self.aesIVData);
if(uncodeAESData){
NSError *error = nil;
NSDictionary *uncodeDict = [NSJSONSerialization JSONObjectWithData:uncodeAESData options:kNilOptions error:&error];
if (error) {
NSString *uncodeJSON = [[NSString alloc] initWithData:uncodeAESData encoding:NSUTF8StringEncoding];
if(uncodeJSON){
NSLog(@"验证解密ServiceMap:%@", uncodeJSON);
}else{
NSLog(@"验证解密ServiceMap: 解析失败:%@", error);
}
} else {
NSLog(@"验证解密ServiceMap:%@",uncodeDict);
}
}
return encryptStr;
}
//初始化AES加密的Key和iv向量数据。
- (void)loadAESKeyAndIVData {
// 设置随机种子为 4728423
NSString *mt19937Str = JKJMT19937Seed(4728423);
NSString *sha256Str = sha256String(mt19937Str);
/*
密钥,截取sha256的64个字节前面32个字节
IV:截取sha256的64个字节前面16个字节
*/
NSString *keyString = substringWithLength(sha256Str, 32);
NSString *ivString = substringWithLength(sha256Str, 16);
//获取AES加密Key
_aesSHA256keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
//获取AES加密的IV向量
_aesIVData = [ivString dataUsingEncoding:NSUTF8StringEncoding];
}
5. 归纳,完成4的操作,用到了一下两个库,a. C++中的random库,实现mt19937随机数;b. CommonCrypto库,实现AES-CBC对称加密,实现SHA256加密。c. 另外Base64是OC中的NSData(NSDataBase64Encoding)分类方法提供。
#include <random>
#import <CommonCrypto/CommonCrypto.h>
6. 补充, AES加密如果需要GCM或者其它(非CBC、非ECB)模式的,可能需要用到如下的方法去实现:a. 使用iOS13之后的库, b. 使用第三方库(libsodium-ios为例)
- a.使用iOS13之后的库代码如下:
//
// AESEncryptor.swift
//
// Created by xw.long on 2024/4/7.
//
import Foundation
import CryptoKit
import CommonCrypto
@available(iOS 13.0, *)
@objc class AESEncryptor: NSObject {
func encryptDataUsingCBCMode(data: Data, key: Data, iv: Data) -> Data? {
let bufferSize = data.count + kCCBlockSizeAES128
var buffer = [UInt8](repeating: 0, count: bufferSize)
var numBytesEncrypted: size_t = 0
let cryptStatus = data.withUnsafeBytes { dataBytes in
key.withUnsafeBytes { keyBytes in
iv.withUnsafeBytes { ivBytes in
CCCrypt(CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
CCOptions(kCCOptionPKCS7Padding),
keyBytes.baseAddress, key.count,
ivBytes.baseAddress,
dataBytes.baseAddress, data.count,
&buffer, bufferSize,
&numBytesEncrypted)
}
}
}
if cryptStatus == kCCSuccess {
return Data(buffer.prefix(Int(numBytesEncrypted)))
} else {
print("Error: \(cryptStatus)")
return nil
}
}
// 加密方法
@objc func encrypt(content: String, key: String, iv: String) -> Data? {
guard let keyData = Data(hexString: key),
let ivData = Data(hexString: iv),
let contentData = content.data(using: .utf8) else {
print("AESEncryptor 无法将输入转换为Data")
return nil
}
do {
// 创建AES密钥
let aesKey = SymmetricKey(data: keyData)
// 使用AES-256-GCM加密
let sealedBox = try AES.GCM.seal(contentData, using: aesKey, nonce: AES.GCM.Nonce(data: ivData))
// 返回加密后的数据
return sealedBox.combined
} catch {
print("AESEncryptor 加密失败: \(error)")
return nil
}
}
// 解密方法
@objc func decrypt(encryptedData: Data, key: String, iv: String) -> String? {
guard let keyData = Data(hexString: key),
let ivData = Data(hexString: iv) else {
print("AESEncryptor 无法将输入转换为Data")
return nil
}
do {
// 创建AES密钥
let aesKey = SymmetricKey(data: keyData)
// 解密
let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)
let decryptedData = try AES.GCM.open(sealedBox, using: aesKey)
// 将解密后的数据转换为字符串
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
print("解密后的数据无法转换为字符串")
return nil
}
return decryptedString
} catch {
print("AESEncryptor 解密失败: \(error)")
return nil
}
}
// 测试方法
@objc static func test() {
let content = "hello world"
let key = "3891346e92151849d58e70de02a05c596b48afe1ae2bdeedf3e69c661c2ea2ae"
let iv = "3891346e9215"
if let encryptedData = AESEncryptor().encrypt(content: content, key: key, iv: iv) {
print("AESEncryptor 加密后的数据: \(encryptedData.base64EncodedString())")
if let decryptedString = AESEncryptor().decrypt(encryptedData: encryptedData, key: key, iv: iv) {
print("AESEncryptor 解密后的字符串: \(decryptedString)")
}
}
}
}
// 十六进制字符串转换为Data扩展
extension Data {
init?(hexString: String) {
var hexString = hexString
var data = Data()
while hexString.count > 0 {
let subIndex = hexString.index(hexString.startIndex, offsetBy: 2)
let hexChar = String(hexString[..<subIndex])
hexString = String(hexString[subIndex...])
guard let byte = UInt8(hexChar, radix: 16) else {
return nil
}
data.append(byte)
}
self = data
}
}
+ (void)swiftTest {
NSString *originalString = @"3891346e92151849d89070de02a05c596b48a123ae2bdeedf3e69c661c2ea2ae";
// 截取新的key和iv
NSString *key = [originalString substringToIndex:32];
NSString *iv = [originalString substringToIndex:12];
// 待加密的内容
NSString *content = @"hello world";
// 调用加密方法
if (@available(iOS 13.0, *)) {
NSData *encryptedData = [[AESEncryptor new] encryptWithContent:content key:key iv:iv];
// 将加密后的数据转换为Base64字符串
NSString *encryptedString = [encryptedData base64EncodedStringWithOptions:0];
NSLog(@"加密后的字符串: %@", encryptedString);
} else {
// Fallback on earlier versions
}
}
- b. 使用第三方库(libsodium-ios为例)
库引用可以通过cocoa-pod方法,在Podfile文件中加入如下代码,并在对应文件目录下执行【pod install】。
platform :ios, '12.0'
也可以通过github 下载:https://github.com/mochtu/libsodium-ios
# Uncomment the next line to define a global platform for your project
platform :ios, '12.0'
target 'MYPROJECT' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for MYPROJECT
pod 'libsodium-ios'
end文章来源:https://www.toymoban.com/news/detail-845482.html
post_install do |pi|
pi.pods_project.targets.each do |t|
t.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
end
end
end
下面是库引入之后得代码示例:文章来源地址https://www.toymoban.com/news/detail-845482.html
#include <sodium.h>
NSData *encryptStringWithAES256EStream(NSString *inputString, const unsigned char *nonce, const unsigned char *key) {
// 转换输入字符串为NSData
NSData *inputData = [inputString dataUsingEncoding:NSUTF8StringEncoding];
// 获取输入数据的长度
NSUInteger inputLength = inputData.length;
// 准备输出缓冲区
NSMutableData *encryptedData = [NSMutableData dataWithLength:inputLength];
// 产生AES-256-ESTREAM流密码
unsigned char stream[inputLength];
crypto_stream_aes256estream(stream, inputLength, nonce, key);
// 对输入数据进行异或运算,实现加密
unsigned char *inputBytes = (unsigned char *)inputData.bytes;
unsigned char *encryptedBytes = (unsigned char *)encryptedData.mutableBytes;
for (NSUInteger i = 0; i < inputLength; i++) {
encryptedBytes[i] = inputBytes[i] ^ stream[i];
}
return encryptedData;
}
+ (void)cryptoTest {
// 初始化libsodium库
if (sodium_init() == -1) {
NSLog(@"libsodium初始化失败");
return;
}
// 长度为16字节的nonce
unsigned char nonce[crypto_stream_aes256estream_NONCEBYTES];
randombytes_buf(nonce, sizeof(nonce));
// 长度为32字节的密钥
unsigned char key[crypto_stream_aes256estream_KEYBYTES];
randombytes_buf(key, sizeof(key));
// 要加密的字符串
NSString *inputString = @"hello world";
// 使用AES-256-ESTREAM密钥流对字符串进行加密
NSData *encryptedData = encryptStringWithAES256EStream(inputString, nonce, key);
// 打印加密后的数据
NSLog(@"加密后的数据:%@", encryptedData);
}
到了这里,关于iOS MT19937随机数生成,结合AES-CBC加密算法实现。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!