详细看参考文章,有几处坑的地方注意
1、引入库的地址问题
Openssl_DSA.m 中引入采用
#include "include/openssl/dsa.h"
#include "include/openssl/md5.h"
#include "include/openssl/pem.h"
2、include/openssl 的引入路径问题,不可以使用编译完成后的 #include <openssl/***.h> 会提示找不到路径,得修改成 #include "***.h"
3、这是修改好后的链接,有需要的可以拿去使用,不过是基于 iPhone15.5SDK版本,链接
iOS版编译完成的OpenSSL库-IOS文档类资源-优快云下载
4、有个巨坑的地方,iOS的sha1方法,签名后的数据本地提示验签通过,但是java和c++端就无法通过,需要使用openssl进行sha1摘要解析,修改代码如下:
.h 部分
//
// Openssl_DSA.h
// ParkingMapSDK
//
// Created by kk on 2022/6/22.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Openssl_DSA : NSObject
- (NSData *)sign:(NSData *)data;
- (void)setUpPrivateKey:(NSString *)privateKey;
- (void)setUpPublicKey:(NSString *)publicKey;
- (BOOL)verify:(NSData *)data withSignData:(NSData *)signData;
@end
NS_ASSUME_NONNULL_END
.m 部分
//
// Openssl_DSA.m
// ParkingMapSDK
//
// Created by kk on 2022/6/22.
//
#import "Openssl_DSA.h"
#include "include/openssl/dsa.h"
#include "include/openssl/md5.h"
#include "include/openssl/pem.h"
#include "include/openssl/evp.h"
@interface Openssl_DSA (){
DSA* _privateDSAKey;
DSA* _publicDSAKey;
}
@end
@implementation Openssl_DSA
/*对数据进行签名
@param data 要签名的数据
@return 签名后数据
*/
- (NSData *)sign:(NSData *)data{
if (_privateDSAKey == nil) {
return nil;
}
// 重点在这里,使用openssl进行 sha1,不要使用iOS的sha1
EVP_MD_CTX *pMdCtx = EVP_MD_CTX_new();
EVP_DigestInit(pMdCtx,EVP_sha1());
EVP_DigestUpdate(pMdCtx, (const unsigned char *) data.bytes, (int)data.length);
unsigned char digest[2048] = {0};
unsigned int dgst_len = 0;
EVP_DigestFinal(pMdCtx, digest, &dgst_len);
unsigned int sig_len = 0;
unsigned char sign_string[2048] = {0};
int res = DSA_sign(NID_dsaWithSHA1, digest, dgst_len, sign_string, &sig_len, _privateDSAKey);
if ( 1 == res ) {
return [[NSData alloc] initWithBytes:sign_string length:sig_len];
}
EVP_MD_CTX_free(pMdCtx);
return nil;
}
/*使用dsa公钥与私钥
@param privateKey 私钥
@param publicKey 公钥
*/
- (void)setUpPrivateKey:(NSString *)privateKey withPublicKey:(NSString *)publicKey {
BIO *bio = BIO_new_mem_buf((void *)[privateKey cStringUsingEncoding:NSUTF8StringEncoding], -1);
_privateDSAKey = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
BIO_free(bio);
bio = BIO_new_mem_buf((void *)[publicKey cStringUsingEncoding:NSUTF8StringEncoding], -1);
_publicDSAKey = PEM_read_bio_DSA_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
}
/*使用dsa私钥
@param privateKey 私钥
*/
- (void)setUpPrivateKey:(NSString *)privateKey {
BIO *bio = BIO_new_mem_buf((void *)[privateKey cStringUsingEncoding:NSUTF8StringEncoding], -1);
// BIO *bio = BIO_new(BIO_s_mem());
// BIO_puts(bio, [privateKey cStringUsingEncoding:NSUTF8StringEncoding]);
_privateDSAKey = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
BIO_free(bio);
}
/*使用dsa公钥
@param publicKey 公钥
*/
- (void)setUpPublicKey:(NSString *)publicKey {
BIO *bio = BIO_new_mem_buf((void *)[publicKey cStringUsingEncoding:NSUTF8StringEncoding], -1);
// BIO *bio = BIO_new(BIO_s_mem());
// BIO_puts(bio, [publicKey cStringUsingEncoding:NSUTF8StringEncoding]);
_publicDSAKey = PEM_read_bio_DSA_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
}
/*进行数据的DSA验签
@param data 原数据
@param signData 签名后的数据
@return 是否成功
*/
- (BOOL)verify:(NSData *)data withSignData:(NSData *)signData {
return DSA_verify(0, (const unsigned char *)[data bytes], (int)data.length, (const unsigned char *)[signData bytes], (int)signData.length, _publicDSAKey) == 1;
}
@end
// 使用
Openssl_DSA *dsa = [Openssl_DSA new];
// 私钥
[dsa setUpPrivateKey: PRIVATE_KEY];
// 公钥
[dsa setUpPublicKey: PUBLIC_KEY];
NSString *sign = @"123";
NSData *sha1Data = [sign dataUsingEncoding:NSUTF8StringEncoding];
NSData *dsaSignData = [dsa sign:sha1Data];
NSString *signStr = [GTMBase64 stringByEncodingData:dsaSignData];
参考文章: