cuur25519加密 ed25519
先导入这两个库
<openssl/rand.h>
<openssl/evp.h>
这里使用的openssl加密套件版本是3.0.7
@property (nonatomic, copy) NSString *publicKey;
@property (nonatomic, copy) NSString *privateKey;
主要逻辑代码都写在下面代码了
椭圆曲线(Elliptic Curve,EC)是密码学中非常重要的代数结构。在公钥加密、数字签名、密钥协商、安全多方计算等领域均有非常广泛的应用 本案展示的是 Curve25519、Ed25519
以下案例是我在实际开发过程中使用到的 这个算法是某些大厂中广泛应用到的加密算法
先说下 整个加密算法分为四部
1.本端生成公私钥对
2.根据对方传来的公钥和本端私钥生成共享密钥
3.通过共享密钥去解密对端传来用来校验的数据
4.进行最终的数据签名和验证
简称ECC算法,是基于数学理论的椭圆曲线来实现的一种“非对称加密”算法。特点:密钥的长度很短,高安全。
第一步生成客户端的公私钥对 因为客户端的秘钥长度要求是64位 所以这里进行base64处理下
- (NSData *)safeBase64EncodingString:(NSString *)str options:(NSInteger)options {
if ([HWTool isEmptyStr:str]) {
return [[NSData alloc] init];
}
return [[NSData alloc] initWithBase64EncodedString:str options:options];
}
// 生成ECC APP公钥和私钥
- (NSArray *)createPublicAndPrivateKey {
EVP_PKEY_CTX *ctx;
EVP_PKEY *evpKey = NULL;
size_t public_keylen = AES256CBC_KEY_LENGTH;
size_t private_keylen = AES256CBC_KEY_LENGTH;
unsigned char *publickey = NULL;
unsigned char *privatekey = NULL;
// 初始化 OpenSSL 库
OpenSSL_add_all_algorithms();
// 生成私钥和公钥
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_keygen(ctx, &evpKey);
// 获取公钥原始数据 EVP_PKEY_get_raw_public_key
if (EVP_PKEY_get_raw_public_key(evpKey, NULL, &public_keylen) != 1) {
printf("Failed to get raw public key length ");
return nil;
}
publickey = (unsigned char *)malloc(public_keylen);
if (EVP_PKEY_get_raw_public_key(evpKey, publickey, &public_keylen) != 1) {
printf("Failed to get raw public key ");
return nil;
}
NSData *publickeyData = [NSData dataWithBytes:publickey length:public_keylen];
if (!publickeyData) {
return nil;
}
}
// 生成手机端公私钥
- (void)createSourePublicKeyAndPrivateKey {
NSArray *array = [self createPublicAndPrivateKey];
// 防止越界 加一个判断
if (array.count >= NUMBER_TWO) {
// 公钥
NSData *publicData = array.firstObject;
self.publicKey = [publicData base64EncodedStringWithOptions:0];
// 私钥
NSData *privateData = array.lastObject;
self.privateKey = [privateData base64EncodedStringWithOptions:0];
}
}
- (int)sign:(NSString *)sign key:(NSString *)publickKey serverInfo:(NSString *)info {
// 验证数据
NSData *oneData = [[NSData alloc] initWithBase64EncodedString:publicKey options:NSDataBase64DecodingIgnoreUnknownCharacters]
NSData *twoData = [[NSData alloc] initWithBase64EncodedString:self.publicKey options:NSDataBase64DecodingIgnoreUnknownCharacters]
NSMutableData *datas = [[NSMutableData alloc] initWithCapacity:0];
[datas appendData:oneData];
[datas appendData:twoData];
NSData *signData = [HWHomeVisionTools safeBase64EncodingString:sign options:NSDataBase64DecodingIgnoreUnknownCharacters];
// ED25519
NSData *public_key = [HWHomeVisionTools safeBase64EncodingString:info
options:NSDataBase64DecodingIgnoreUnknownCharacters];
BOOL isSuccess = [self verfitySignData:datas key:signData serverInfo:public_key];
return isSuccess;
}
// 根据对端公钥生成共享密钥
// @param peerKey 对端公钥
- (NSString *)getShareKeyWithPeerKey:(NSString *)peerKey {
NSData *privateData = [HWHomeVisionTools safeBase64EncodingString:self.privateKey
options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSData *peerData = [HWHomeVisionTools safeBase64EncodingString:peerKey
options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSData *shareData = [self eccPublicSharedKeyWithServerPubKey:peerData appPrivateKey:privateData];
NSString *shareKeyStr = [shareData base64EncodedStringWithOptions:0];
if (shareKeyStr.length == NUMBER_ZERO) {
return @"";
}
return shareKeyStr;
}
// 生成ECC APP公钥和私钥
- (NSArray *)createPublicAndPrivateKey {
EVP_PKEY_CTX *ctx;
EVP_PKEY *evpKey = NULL;
size_t public_keylen = AES256CBC_KEY_LENGTH;
size_t private_keylen = AES256CBC_KEY_LENGTH;
unsigned char *publickey = NULL;
unsigned char *privatekey = NULL;
// 初始化 OpenSSL 库
OpenSSL_add_all_algorithms();
// 生成私钥和公钥
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_keygen(ctx, &evpKey);
// 获取私钥原始数据 EVP_PKEY_get_raw_private_key
if (EVP_PKEY_get_raw_private_key(evpKey, NULL, &private_keylen) != 1) {
printf("Failed to get raw private key length ");
}
privatekey = (unsigned char *)malloc(private_keylen);
if (EVP_PKEY_get_raw_private_key(evpKey, privatekey, &private_keylen) != 1) {
printf("Failed to get raw private key ");
}
NSData *privateKeyData = [NSData dataWithBytes:privatekey length:private_keylen];
if (!privateKeyData) {
return nil;
}
NSArray *dataArray = @[publickeyData, privateKeyData];
// 释放内存
EVP_PKEY_free(evpKey);
evpKey = NULL;
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
memset_s(publickey, public_keylen, 0, public_keylen);
free(publickey);
publickey = NULL;
memset_s(privatekey, private_keylen, 0, private_keylen);
free(privatekey);
privatekey = NULL;
// 清理 OpenSSL 库
EVP_cleanup();
return dataArray;
}
// 密钥交换生成共享密钥
- (NSData *)eccPublicSharedKeyWithServerPubKey:(NSData *)serverPubKey appPrivateKey:(NSData *)appPrivateKey {
if (!serverPubKey || serverPubKey.length == NUMBER_ZERO || !appPrivateKey || appPrivateKey.length ==NUMBER_ZERO) {
return nil;
}
EVP_PKEY_CTX *ctx;
EVP_PKEY *private_key, *public_key;
size_t length = AES256CBC_KEY_LENGTH;
public_key = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, [serverPubKey bytes], length);
private_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, [appPrivateKey bytes], length);
ctx = EVP_PKEY_CTX_new(private_key, NULL);
EVP_PKEY_derive_init(ctx);
EVP_PKEY_derive_set_peer(ctx, public_key);
unsigned char *shared_secret;
size_t shared_secret_len;
EVP_PKEY_derive(ctx, NULL, &shared_secret_len);
shared_secret = (unsigned char *)OPENSSL_malloc(shared_secret_len);
EVP_PKEY_derive(ctx, shared_secret, &shared_secret_len);
if (shared_secret == NULL) {
return nil;
}
NSData *data = [NSData dataWithBytes:shared_secret length:length];
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
memset_s(shared_secret, shared_secret_len, 0, shared_secret_len);
free(shared_secret);
shared_secret = NULL;
return data;
}
// 数据验证
- (BOOL)verfitySignData:(NSData *)signData key:(NSData *)publickKey serverInfo:(NSData *)info {
if (signData.length == NUMBER_ZERO || publickKey.length == NUMBER_ZERO || info.length == NUMBER_ZERO) {
return nil;
}
EVP_PKEY_CTX *ctx;
EVP_PKEY *public_key;
size_t length = AES256CBC_KEY_LENGTH;
// 共享密钥
public_key = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, [publickKey bytes], length);
ctx = EVP_PKEY_CTX_new(public_key, NULL);
EVP_PKEY_derive_init(ctx);
BOOL isSuccess = EVP_PKEY_verify(ctx, signData.bytes, signData.length, info.bytes, info.length);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(public_key);
ctx = NULL;
return isSuccess;
}
IV_LENGTH 为12位偏移量
#pragma mark - AES-GCM256 解密
+ (NSData *)aesGcm256DecryptKey:(NSData *)keyData message:(NSData *)message {
// 将密文拆分为iv+key
int inputLength = (int)[message length];
int decrypuLength = 0;
NSData *iv = [NSData data];
if (inputLength > (IV_LENGTH + VERSION_LENGTH)) {
iv = [message subdataWithRange:NSMakeRange(VERSION_LENGTH, IV_LENGTH)];
decrypuLength = (int)(inputLength - IV_LENGTH - VERSION_LENGTH);
}
NSData *inputData = [message subdataWithRange:NSMakeRange(IV_LENGTH + VERSION_LENGTH, decrypuLength)];
NSData *cipher = [AESCipher AESGcm256Decrypt:inputData withKey:keyData iv:iv];
return cipher;
}
#pragma mark - AES-GCM256 加密
+ (NSData *)aesGcm256EncryptKey:(NSData *)keyData message:(NSData *)message {
NSMutableData *sendData = [[NSMutableData alloc] initWithCapacity:0];
Byte byte[] = {00}; // 1个字节
NSData *versionData = [[NSData alloc] initWithBytes:byte length:1];
[sendData appendData:versionData];
NSData *ivData = [[NSMutableData alloc] init];
// 验证随机数
Byte randomBytes[12];
int ivResult = SecRandomCopyBytes(kSecRandomDefault, 12, randomBytes);
// 验证结果返回0表示成功 其他值失败
if(ivResult == 0) {
ivData = [[NSMutableData alloc] initWithBytes:randomBytes length:12];
}
[sendData appendData:ivData];
NSData*encrytData = [AESCipher AESGcm256Encrypt:message withKey:keyData iv:ivData];
[sendData appendData:encrytData];
return sendData;
}
本文是原创文章,完整转载请注明来自 MrXiao's Blog
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果