{"id":21373900,"url":"https://github.com/cocoajin/Security-iOS","last_synced_at":"2025-07-13T08:31:22.506Z","repository":{"id":73300192,"uuid":"76619712","full_name":"cocoajin/Security-iOS","owner":"cocoajin","description":"some NSData Category for doing RSA,AES,MD5,SHA1,SHA256,Sign,Verify on iOS Cryptography","archived":false,"fork":false,"pushed_at":"2016-12-16T06:57:56.000Z","size":23,"stargazers_count":89,"open_issues_count":0,"forks_count":26,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-11-22T08:38:18.884Z","etag":null,"topics":["cbc","ecb","hash","rsa"],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cocoajin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SecurityiOS.xcodeproj/project.pbxproj","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-16T03:58:34.000Z","updated_at":"2024-02-19T17:05:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"6f58a9eb-38e1-466c-b1b2-02a08c6903d4","html_url":"https://github.com/cocoajin/Security-iOS","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cocoajin/Security-iOS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoajin%2FSecurity-iOS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoajin%2FSecurity-iOS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoajin%2FSecurity-iOS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoajin%2FSecurity-iOS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cocoajin","download_url":"https://codeload.github.com/cocoajin/Security-iOS/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoajin%2FSecurity-iOS/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265109710,"owners_count":23712742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cbc","ecb","hash","rsa"],"created_at":"2024-11-22T08:29:34.877Z","updated_at":"2025-07-13T08:31:22.492Z","avatar_url":"https://github.com/cocoajin.png","language":"Objective-C","funding_links":[],"categories":["OOM-Leaks-Crash"],"sub_categories":["数据安全和算法"],"readme":"# Security-iOS\n\n封装了一些iOS上使用的NSData分类，主要用于 `RSA加密`,`AES加密`,`数据签名`,`签名校验`,`MD5 SHA1 SHA256 常用hash`等工具。\n\n主要使用的是iOS上 `Security.framework` 和 `CommonCrypto` 接口\n\n支持iOS2.0+开发\n\n\n## md5,sha1,sha256常用hash\n\n 接口文件和源码 `NSData+KKHASH.h`,`NSData+KKHASH.m`\n\n支持的hash算法有\n\n```objective-c\ntypedef enum : NSUInteger {\n    //md2 16字节长度\n    CCDIGEST_MD2 = 1000,\n    //md4 16字节长度\n    CCDIGEST_MD4,\n    //md5 16字节长度\n    CCDIGEST_MD5,\n    //sha1 20字节长度\n    CCDIGEST_SHA1,\n    //SHA224 28字节长度\n    CCDIGEST_SHA224,\n    //SHA256 32字节长度\n    CCDIGEST_SHA256,\n    //SHA384 48字节长度\n    CCDIGEST_SHA384,\n    //SHA512 64字节长度\n    CCDIGEST_SHA512,\n} CCDIGESTAlgorithm;\n```\n\n调用接口\n\n```objective-c\n/**\n    计算数据的hash值，根据不同的算法\n */\n- (NSData *)hashDataWith:(CCDIGESTAlgorithm )ccAlgorithm;\n\n\n/**\n    返回 hex string的 data\n */\n- (NSString *)hexString;\n```\n\n调用示例\n\n```objective-c\n//测试哈希函数\n- (void)testKKHASHTools\n{\n    //以下结果由openssl dtsg 命令得出的结果，并和这里相比对\n    NSString *tpath = [[NSBundle mainBundle] pathForResource:@\"src.txt\" ofType:nil];\n    NSData *test = [NSData dataWithContentsOfFile:tpath];\n    NSLog(@\"%@\",[[test hashDataWith:CCDIGEST_MD2] hexString]);\n    if([[[test hashDataWith:CCDIGEST_MD4] hexString] isEqualToString:@\"a695ea9f14a89c4e82ca5cf52a28d45d\"])\n    {\n        NSLog(@\"MD4 TEST PASS\");\n    }\n    if([[[test hashDataWith:CCDIGEST_MD5] hexString] isEqualToString:@\"781e5e245d69b566979b86e28d23f2c7\"])\n    {\n        NSLog(@\"MD5 TEST PASS\");\n    }\n    if([[[test hashDataWith:CCDIGEST_SHA1] hexString] isEqualToString:@\"87acec17cd9dcd20a716cc2cf67417b71c8a7016\"])\n    {\n        NSLog(@\"SHA1 TEST PASS\");\n    }\n    if([[[test hashDataWith:CCDIGEST_SHA224] hexString] isEqualToString:@\"f28ad8ecd48ba6f914c114821685ad08f0d6103649ff156599a90426\"])\n    {\n        NSLog(@\"SHA224 TEST PASS\");\n    }\n    if([[[test hashDataWith:CCDIGEST_SHA256] hexString] isEqualToString:@\"84d89877f0d4041efb6bf91a16f0248f2fd573e6af05c19f96bedb9f882f7882\"])\n    {\n        NSLog(@\"SHA256 TEST PASS\");\n    }\n    if([[[test hashDataWith:CCDIGEST_SHA384] hexString] isEqualToString:@\"90ae531f24e48697904a4d0286f354c50a350ebb6c2b9efcb22f71c96ceaeffc11c6095e9ca0df0ec30bf685dcf2e5e5\"])\n    {\n        NSLog(@\"SHA384 TEST PASS\");\n    }\n    if([[[test hashDataWith:CCDIGEST_SHA512] hexString] isEqualToString:@\"bb96c2fc40d2d54617d6f276febe571f623a8dadf0b734855299b0e107fda32cf6b69f2da32b36445d73690b93cbd0f7bfc20e0f7f28553d2a4428f23b716e90\"])\n    {\n        NSLog(@\"SHA512 TEST PASS\");\n    }\n\n}\n```\n\n## AES 加密解密\n\n接口文件和源码 `NSData+KKAES.h`,`NSData+KKAES.m`\n\n支持AES cbc,ecb两种模式，默认使用的填充方式 `kCCOptionPKCS7Padding`.\n可以参考更多 [iOS CommonCrypto 对称加密 AES ecb,cbc](http://www.cnblogs.com/cocoajin/p/6150203.html)\n\n主要接口\n\n```objective-c\n/**\n    AES cbc 模式加密，\n    @key 长度16字节，24字节，32字节\n    @iv 16字节\n */\n- (NSData *)AES_CBC_EncryptWith:(NSData *)key iv:(NSData *)iv;\n\n/**\n    AES cbc 模式解密，\n    @key 长度16字节，24字节，32字节\n    @iv 16字节\n */\n- (NSData *)AES_CBC_DecryptWith:(NSData *)key iv:(NSData *)iv;\n\n/**\n    AES ecb 模式加密，\n    @key 长度16字节，24字节，32字节\n */\n- (NSData *)AES_ECB_EncryptWith:(NSData *)key;\n\n/**\n    AES ecb 模式解密，\n    @key 长度16字节，24字节，32字节\n */\n- (NSData *)AES_ECB_DecryptWith:(NSData *)key;\n```\n\n调用示例\n\n```objective-c\n    NSData *key16 = [@\"0123456789123456\" dataUsingEncoding:NSUTF8StringEncoding];\n    NSData *key24 = [@\"012345678901234567891234\" dataUsingEncoding:NSUTF8StringEncoding];\n    NSData *key32 = [@\"01234567890123456789012345678912\" dataUsingEncoding:NSUTF8StringEncoding];\n    NSData *iv16 = [@\"0123456789654321\" dataUsingEncoding:NSUTF8StringEncoding];\n    NSData *srcData = [@\"this is src test data\" dataUsingEncoding:NSUTF8StringEncoding];\n    NSLog(@\"%@\",srcData);\n    \n    \n    \n    NSData *dec16 = [[srcData AES_CBC_EncryptWith:key16 iv:iv16] AES_CBC_DecryptWith:key16 iv:iv16];\n    if (memcmp(srcData.bytes, dec16.bytes, srcData.length)==0) {\n        NSLog(@\"AES_cbc_16 PASS\");\n    }\n    \n    \n    NSData *dec24 = [[srcData AES_CBC_EncryptWith:key24 iv:iv16] AES_CBC_DecryptWith:key24 iv:iv16];\n    if (memcmp(srcData.bytes, dec24.bytes, srcData.length)==0) {\n        NSLog(@\"AES_cbc_24 PASS\");\n    }\n    \n    \n    NSData *dec32 = [[srcData AES_CBC_EncryptWith:key32 iv:iv16] AES_CBC_DecryptWith:key32 iv:iv16];\n    if (memcmp(srcData.bytes, dec32.bytes, srcData.length)==0) {\n        NSLog(@\"AES_cbc_32 PASS\");\n    }\n    \n    \n    \n    \n    NSData *edec16 = [[srcData AES_ECB_EncryptWith:key16] AES_ECB_DecryptWith:key16];\n    if (memcmp(srcData.bytes, edec16.bytes, srcData.length)==0) {\n        NSLog(@\"AES_ecb_16 PASS\");\n    }\n    \n    \n    NSData *edec24 = [[srcData AES_ECB_EncryptWith:key24] AES_ECB_DecryptWith:key24];\n    if (memcmp(srcData.bytes, edec24.bytes, srcData.length)==0) {\n        NSLog(@\"AES_ecb_24 PASS\");\n    }\n    \n    \n    NSData *edec32 = [[srcData AES_ECB_EncryptWith:key32] AES_ECB_DecryptWith:key32];\n    if (memcmp(srcData.bytes, edec32.bytes, srcData.length)==0) {\n        NSLog(@\"AES_ecb_32 PASS\");\n    }\n```\n\n\n## RSA 加密解密\n\n接口和源码 `NSData+KKRSA.h`,`NSData+KKRSA.m`\n\n支持的RSA密钥位数：512,768,1024,2048等;\n可以参考更多 [iOS使用Security.framework进行RSA 加密解密签名和验证签名](http://www.cnblogs.com/cocoajin/p/6183443.html)\n\n支持的填充方式\n\n```objective-c\n//分组加密，支持最大的加密块为 block 和填充方式有关\ntypedef enum : NSUInteger {\n    //不填充，最大数据块为 blockSize\n    RSAPaddingNONE,\n    //填充方式pkcs1,最大数据块为 blockSize -11\n    RSAPaddingPKCS1,\n    //填充方式OAEP, 最大数据块为 blockSize -42\n    RSAPaddingOAEP,\n} RSAPaddingTYPE;\n```\n\n调用接口\n\n```objective-c\n/**\n    公钥加密\n */\n- (NSData *)RSAEncryptWith:(SecKeyRef )publicKey paddingType:(RSAPaddingTYPE )pdType;\n\n/**\n    私钥解密\n */\n- (NSData *)RSADecryptWith:(SecKeyRef )privateKey paddingType:(RSAPaddingTYPE )pdType;\n```\n\n调用示例\n\n```objective-c\n//生成RSA密钥对，公钥和私钥，支持的SIZE有\n// sizes for RSA keys are: 512, 768, 1024, 2048.\n- (void)generateRSAKeyPair:(int )keySize\n{\n    if (publicKeyRef) {\n        return;\n    }\n    OSStatus ret = 0;\n    publicKeyRef = NULL;\n    privateKeyRef = NULL;\n    ret = SecKeyGeneratePair((CFDictionaryRef)@{(id)kSecAttrKeyType:(id)kSecAttrKeyTypeRSA,(id)kSecAttrKeySizeInBits:@(keySize)}, \u0026publicKeyRef, \u0026privateKeyRef);\n    NSAssert(ret==errSecSuccess, @\"密钥对生成失败：%d\",ret);\n    \n    NSLog(@\"%@\",publicKeyRef);\n    NSLog(@\"%@\",privateKeyRef);\n    NSLog(@\"max size:%lu\",SecKeyGetBlockSize(privateKeyRef));\n    \n}\n\n    //生成密钥对\n    [self generateRSAKeyPair:kRSA_KEY_SIZE];\n    \n    NSData *srcData = [@\"01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567\" dataUsingEncoding:NSASCIIStringEncoding];\n    //max 128\n    NSData *decData = [[srcData RSAEncryptWith:publicKeyRef paddingType:RSAPaddingNONE] RSADecryptWith:privateKeyRef paddingType:RSAPaddingNONE];\n    \n    if (memcmp(srcData.bytes, decData.bytes, srcData.length)==0) {\n        NSLog(@\"RSA RSAPaddingNONE TEST PASS\");\n    }\n    \n    \n    NSData *srcData2 = [@\"012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456\" dataUsingEncoding:NSASCIIStringEncoding];\n    //max 128-11 117\n    NSData *decData2 = [[srcData2 RSAEncryptWith:publicKeyRef paddingType:RSAPaddingPKCS1]\n                        RSADecryptWith:privateKeyRef paddingType:RSAPaddingPKCS1];\n    \n    if (memcmp(srcData2.bytes, decData2.bytes, srcData2.length)==0) {\n        NSLog(@\"RSA RSAPaddingPKCS1 TEST PASS\");\n    }\n    \n    \n    NSData *srcData3 = [@\"01234567890123456789012345678901234567890123456789012345678901234567890123456789123456\" dataUsingEncoding:NSASCIIStringEncoding];\n    //max 128-42 86\n    NSData *decData3 = [[srcData3 RSAEncryptWith:publicKeyRef paddingType:RSAPaddingOAEP] RSADecryptWith:privateKeyRef paddingType:RSAPaddingOAEP];\n    \n    if (memcmp(srcData3.bytes, decData3.bytes, srcData3.length)==0) {\n        NSLog(@\"RSA RSAPaddingOAEP TEST PASS\");\n    }\n```\n\n\n## RSA签名验证签名\n\n接口文件和源码 `NSData+KKSignVerify.h`,`NSData+KKSignVerify.m`\n\n数据签名一般签名数据的hash值，配合上面的HASH函数使用\n\n支持的签名算法\n\n```objective-c\n//主要使用PKCS1 方式的填充，最大签名数据长度为blockSize-11\n//签名算法从ios5以后不再支持md5,md2\ntypedef enum : NSUInteger {\n    SEC_PKCS1SHA1 = 2000,\n    SEC_PKCS1SHA224,\n    SEC_PKCS1SHA256,\n    SEC_PKCS1SHA384,\n    SEC_PKCS1SHA512,\n} SEC_PKCS1_ALGORITHM;\n```\n\n主要接口\n\n```objective-c\n/**\n    根据不同的算法，签名数据，\n */\n- (NSData *)signDataWith:(SecKeyRef)privateKey algorithm:(SEC_PKCS1_ALGORITHM )ccAlgorithm;\n\n/**\n    验证签名数据\n */\n- (BOOL)verifySignWith:(SecKeyRef)publicKey signData:(NSData *)signData algorithm:(SEC_PKCS1_ALGORITHM )ccAlgorithm;\n```\n\n调用示例\n\n```objective-c\n\t\t//生成RSA密钥对，\n    [self generateRSAKeyPair:kRSA_KEY_SIZE];\n    \n    NSString *tpath = [[NSBundle mainBundle] pathForResource:@\"src.txt\" ofType:nil];\n    NSData *ttDt = [NSData dataWithContentsOfFile:tpath];\n    NSData *sha1dg = [ttDt hashDataWith:CCDIGEST_MD4];\n    \n\n    if ([sha1dg verifySignWith:publicKeyRef signData:[sha1dg signDataWith:privateKeyRef algorithm:SEC_PKCS1SHA1] algorithm:SEC_PKCS1SHA1]) {\n        NSLog(@\"SIGN-VERIFY sha1 PASS\");\n    }\n    \n    if ([sha1dg verifySignWith:publicKeyRef signData:[sha1dg signDataWith:privateKeyRef algorithm:SEC_PKCS1SHA224] algorithm:SEC_PKCS1SHA224]) {\n        NSLog(@\"SIGN-VERIFY sha224 PASS\");\n    }\n    \n    if ([sha1dg verifySignWith:publicKeyRef signData:[sha1dg signDataWith:privateKeyRef algorithm:SEC_PKCS1SHA256] algorithm:SEC_PKCS1SHA256]) {\n        NSLog(@\"SIGN-VERIFY sha256 PASS\");\n    }\n    \n    if ([sha1dg verifySignWith:publicKeyRef signData:[sha1dg signDataWith:privateKeyRef algorithm:SEC_PKCS1SHA384] algorithm:SEC_PKCS1SHA384]) {\n        NSLog(@\"SIGN-VERIFY sha384 PASS\");\n    }\n    if ([sha1dg verifySignWith:publicKeyRef signData:[sha1dg signDataWith:privateKeyRef algorithm:SEC_PKCS1SHA512] algorithm:SEC_PKCS1SHA512]) {\n        NSLog(@\"SIGN-VERIFY sha512 PASS\");\n    }\n```\n\n## RSA密钥管理\n\n接口文件和源码 `SecKeyTools.h`,`SecKeyTools.m`\n\n主要用于读取密钥文件中的密钥，如从证书中读取公钥，从p12文件中读取私钥等操作；\nRSA相关的密钥放在手机上是不安全的，但是也没有绝对的安全，视业务情况来定吧。\n\n主要接口\n\n```objective-c\n\n/**\n    从x509 cer证书中读取公钥\n */\n+ (SecKeyRef )publicKeyFromCer:(NSString *)cerFile;\n\n\n/**\n    从 p12 文件中读取私钥，一般p12都有密码\n */\n+ (SecKeyRef )privateKeyFromP12:(NSString *)p12File password:(NSString *)pwd;\n\n\n/**\n    iOS 10 上可用如下接口SecKeyCreateWithData 从pem文件中读取私钥或公钥\n */\n+ (SecKeyRef )publicKeyFromPem:(NSString *)pemFile keySize:(size_t )size;\n\n+ (SecKeyRef )privaKeyFromPem:(NSString *)pemFile keySize:(size_t )size;\n```\n\n调用示例\n\n```objective-c\n    NSString *cerPA = [[NSBundle mainBundle] pathForResource:@\"CPPUB.cer\" ofType:nil];\n    NSString *p12PA = [[NSBundle mainBundle] pathForResource:@\"CPPRI.p12\" ofType:nil];\n    \n    SecKeyRef pubkey = [SecKeyTools publicKeyFromCer:cerPA];\n    SecKeyRef prikey = [SecKeyTools privateKeyFromP12:p12PA password:@\"test\"];\n\n    NSLog(@\"%@\",pubkey);\n    NSLog(@\"%@\",prikey);\n    \n    NSLog(@\"%lu\",SecKeyGetBlockSize(prikey));\n    \n    \n    NSData *srcData = [@\"0123456789\" dataUsingEncoding:NSUTF8StringEncoding];\n    NSLog(@\"%@\",srcData);\n    NSData *encDT = [srcData RSAEncryptWith:pubkey paddingType:RSAPaddingPKCS1];\n    NSData *decDT = [encDT RSADecryptWith:prikey paddingType:RSAPaddingPKCS1];\n    NSLog(@\"%@\",decDT);\n    \n    \n    \n    NSString *pripem = [[NSBundle mainBundle] pathForResource:@\"private.pem\" ofType:nil];\n    NSString *pubpem = [[NSBundle mainBundle] pathForResource:@\"public.pem\" ofType:nil];\n    SecKeyRef pubKK = [SecKeyTools publicKeyFromPem:pubpem keySize:kRSA_KEY_SIZE];\n    SecKeyRef priKK = [SecKeyTools privaKeyFromPem:pripem keySize:kRSA_KEY_SIZE];\n    NSLog(@\"%@\",pubKK);\n    NSLog(@\"%@\",priKK);\n    \n    NSLog(@\"%lu\",SecKeyGetBlockSize(priKK));\n    NSData *srcData2 = [@\"0123456789\" dataUsingEncoding:NSUTF8StringEncoding];\n    NSLog(@\"%@\",srcData2);\n    NSData *encDT2 = [srcData2 RSAEncryptWith:pubKK paddingType:RSAPaddingPKCS1];\n    NSData *decDT2 = [encDT2 RSADecryptWith:priKK paddingType:RSAPaddingPKCS1];\n    NSLog(@\"%@\",decDT2);\n```\n\n\n## 其他\n\n\n- 密钥对的生成\n\n```objective-c\n//生成RSA密钥对，公钥和私钥，支持的SIZE有\n// sizes for RSA keys are: 512, 768, 1024, 2048.\n- (void)generateRSAKeyPair:(int )keySize\n{\n    if (publicKeyRef) {\n        return;\n    }\n    OSStatus ret = 0;\n    publicKeyRef = NULL;\n    privateKeyRef = NULL;\n    ret = SecKeyGeneratePair((CFDictionaryRef)@{(id)kSecAttrKeyType:(id)kSecAttrKeyTypeRSA,(id)kSecAttrKeySizeInBits:@(keySize)}, \u0026publicKeyRef, \u0026privateKeyRef);\n    NSAssert(ret==errSecSuccess, @\"密钥对生成失败：%d\",ret);\n    \n    NSLog(@\"%@\",publicKeyRef);\n    NSLog(@\"%@\",privateKeyRef);\n    NSLog(@\"max size:%lu\",SecKeyGetBlockSize(privateKeyRef));\n    \n}\n```\n\n- RSA上几种填充方式的区别\n\n```objective-c\n/** 三种填充方式区别\n kSecPaddingNone      = 0,   要加密的数据块大小\u003c＝SecKeyGetBlockSize的大小，如这里128\n kSecPaddingPKCS1     = 1,   要加密的数据块大小\u003c=128-11\n kSecPaddingOAEP      = 2,   要加密的数据块大小\u003c=128-42\n  密码学中的设计原则，一般用RSA来加密 对称密钥，用对称密钥加密大量的数据\n  非对称加密速度慢，对称加密速度快\n */\n```\n\n- 示例工程 `SecurityiOS.xcodeproj`\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcocoajin%2FSecurity-iOS","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcocoajin%2FSecurity-iOS","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcocoajin%2FSecurity-iOS/lists"}