分享在Mac 和 iOS 上使用到的对称和非对称加密算法. 包括RSA,DSA, AES, DES, 3DES 和 blowfish 等等.
因为要实现ssh协议, 所以用到了这些算法, 这些算法在mac和ios上的接口比较难用, 我在这折腾了好长时间, 这里分享出来, 希望对大家有帮助.
(这里不提 openssl 在 apple 上的接口了)

主要参考了apple的文档:

Cryptographic Services Guide

Apple Encrypting and Hashing Data

先大致概括一下整体情况:
基本上这两个平台上的加密解密都和 keychain service 密不可分. keychain是mac和ios上用来保存证书,密码,key 等等敏感信息的存储区. 有专门的api访问这些接口. 有时候我们为了获得一个 key 的实例,必须想办法把数据导入到keychain中,然后才能通过keychain获得一个key的实例. 后面再说.

在mac 上, 有三个方式实现加密解密签名服务:

  1. Security Transforms API —a Core-Foundation-level API that provides support for signing and verifying, symmetric cryptography, and Base64 encoding and decoding.
    是 CoreFoundation 级别的api, 提供了, 最全的功能和算法支持. 包括对称,非对称算法. 实现加密,签名功能. 但遗憾的是这个接口只在mac上有效. iOS上没有. 但有些功能必须要用到, 所以要实现跨平台的代码,需要一些补丁.

  2. Common Crypto—a C-level API that can perform most symmetric encryption and decryption tasks
    这是一个 C 风格的接口. 好消息是它在mac和ios上都有, 可以跨平台. 但坏消息是, 它只包含了, 对称加密算法, 却没有非对称算法. 因此只能加密解密,而不能签名和验证. 其实之前 Apple上还有一个 ComonCryptoRSA 模块, 但后来不知为何消失了.

  3. CDSA/CSSM —a legacy API that should be used only to perform tasks not supported by the other two APIs, such as asymmetric encryption
    这个名字比较吓人, Common Data Security Architecture (CDSA) 通用数据安全架构. 很奇怪,它被apple接受后不久, 就被废弃了. 现在已经不建议使用了. 所以就不提它了.

在 iOS 上, 基本上有两种方式:

  1. Common Crypto. 这个在上面已经说过了. 对称算法接口.

  2. 使用系统提供的特有api实现加密,解密, 签名和验证:

系统提供了下面4个函数:

SecKeyEncrypt—encrypts a block of data using the specified key.SecKeyDecrypt—decrypts a block of data using the specified key.SecKeyRawSign—signs a block of data using the specified key.SecKeyRawVerify—verifies a signature against a block of data and a specified key.

基于上面的分析, 我们秉着尽可能减少代码重复, 跨平台开发的原则: 对称算法就使用 “Common Crypto” 模块了. 因为两个平台都有. 而非对称则需要分别实现了.

下面详细分享一些细节:

一, 非对称加密算法, 签名和验证.(RSA/DSA signature and verity)

这需要在两个平台独立开发.

  1. Mac 平台.

在 mac 平台上, 我们使用它的 Security Transforms API.

参考这里: Security Transforms Programming Guide-Signing and Verifying

上面有很好的 代码 片段. 需要注意的是如何把 RSA 的参数 变成 api 需要的 SecKeyRef 对象.

这是它的导入片段.

    params.keyUsage = NULL;params.keyAttributes = NULL;SecExternalItemType itemType = kSecItemTypeCertificate;SecExternalFormat externalFormat = kSecFormatPEMSequence;int flags = 0;oserr = SecItemImport(cfdataprivatekey,NULL, // filename or extension&externalFormat, // See SecExternalFormat for details&itemType, // item typeflags, // See SecItemImportExportFlags for details&params,NULL, // Don't import into a keychain&temparray);if (oserr) {fprintf(stderr, "SecItemImport failed (oserr=%d)\n", oserr);CFShow(temparray);exit(-1);}privatekey = (SecKeyRef)CFArrayGetValueAtIndex(temparray, 0);

这里是为了创建 SecKeyRef 实例. 通过 SecItemImport 把数据导入.变成SecKeyRef实例. 数据放在 cfdataprivatekey 中. 这个数据必须是 Pem格式的证书. 因为这个case下需要私钥, 所以这个证书需要包含私钥, 都是pem格式.

这里特别介绍一下, 如何从ssh 的公钥格式导入. 以RSA为例, RSA的公钥其实是一个底数e, 和一个大整数 m ,

e = [int32(len), bytes(value)]
m = [int32(len), bytes(value)]

e 和 m 的结构一样. 先是4个字节的长度, 然后紧跟上字节序列. len是 大端在前的, 跟通常的小端是有区别的.
完整的机构大概是这个样子的:

Binary = [0x00, 0x00, 0x00, 0x07, 'ssh-rsa', e, m]keydata = 'ssh-rsa' + Base64Encode(Binary)

这个keydata 就可以用来构建上面用到的参数cfdataprivatekey了.

对于DSA, 结构跟上面类似:

p = [int32(len), bytes(value)]
q = [int32(len), bytes(value)]
g = [int32(len), bytes(value)]
y = [int32(len), bytes(value)]Binary = [0x00, 0x00, 0x00, 0x07, 'ssh-dss', p, q, g, y]keydata = 'ssh-dss' + Base64Encode(Binary)
  1. 对于 iOS, 平台, 我们使用上面说的两个函数来签名和验证:
SecKeyRawSign—signs a block of data using the specified key.SecKeyRawVerify—verifies a signature against a block of data and a specified key.

这两个函数要命的是都需要一个 SecKeyRef 参数, iOS 上还真没有直接的方式可以通过大整数直接创建 SecKeyRef的实例.

要么通过 keychain 读取. 或者通过 SecPKCS12Import() 函数导入 pkcs12 格式的包含私钥的证书, 然后获得 SecIdentityRef 实例. 然后再通过 SecIdentityCopyPrivateKey() 函数把其中的 私钥导出成 SecKeyRef实例.

OSStatus extractIdentityAndTrust(CFDataRef inPKCS12Data,SecIdentityRef *outIdentity,SecTrustRef *outTrust,CFStringRef keyPassword)
{OSStatus securityError = errSecSuccess;const void *keys[] =   { kSecImportExportPassphrase };const void *values[] = { keyPassword };CFDictionaryRef optionsDictionary = NULL;/* Create a dictionary containing the passphrase if onewas specified.  Otherwise, create an empty dictionary. */optionsDictionary = CFDictionaryCreate(NULL, keys,values, (keyPassword ? 1 : 0),NULL, NULL);  // 1CFArrayRef items = NULL;securityError = SecPKCS12Import(inPKCS12Data,optionsDictionary,&items);                    // 2//if (securityError == 0) {                                   // 3CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);const void *tempIdentity = NULL;tempIdentity = CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity);CFRetain(tempIdentity);*outIdentity = (SecIdentityRef)tempIdentity;const void *tempTrust = NULL;tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);CFRetain(tempTrust);*outTrust = (SecTrustRef)tempTrust;}if (optionsDictionary)                                      // 4CFRelease(optionsDictionary);if (items)CFRelease(items);return securityError;
}

另外一个方法是, 苹果官方给的示例代码, 强制拼凑 SecKeyRef示例.
这里有 SecKeyWrapper 的实例代码: SecKeyWrapper 的实例代码

并且可以在这里直接下载到 源码: SecKeyWrapper 源码

这个源码里面有很多 苹果写的例子. 非常好. 对剑使用这里面的代码实现.

二, 对于对称加密算法.
这个比较简单了, 我们直接使用 Common Crypto 模块. 在mac 和ios上可以跨平台.

请参考这里: Apple Common Crypto library

  1. 使用 CCCryptorCreate 或者 CCCryptorCreateWithMode 创建 CCCryptorRef 对象.
    然后不断的调用 CCCryptorUpdate. 进行加密/解密.
    最后调用:CCCryptorFinal. 获取最后一块加密方法.

建议使用 CCCryptorCreateWithMode 方法.因为它能指定更多的参数. 比如 加密算法的padding 和ciphermode.

最后再顺便分享一下Mac 和iOS上生成 密码学安全的随机数的方法: Generating Random Numbers

简单的来说. 在mac上, 可以通过 fopen 读取 /dev/random 设备获得密码学安全的随机数.

FILE *fp = fopen("/dev/random", "r");if (!fp) {perror("randgetter");exit(-1);
}uint64_t value = 0;
int i;
for (i=0; i<sizeof(value); i++) {value <<= 8;value |= fgetc(fp);
}fclose(fp);

而在 iOS 上, 由于不能读取设备, 它提供了 专门的 方法: SecRandomCopyBytes , 用起来非常简单.

欢迎访问我的独立博客 https://blog.byneil.com

转载于:https://www.cnblogs.com/shuidao/p/4392312.html

Mac和 iOS 下的对称和非对称加密算法的使用相关推荐

  1. android 对称加密和非对称加密,Android开发加密之对称与非对称加密算法使用案例.pdf...

    Android开发加密之对称与非对称加密算法使用案例 消息摘要 md5:登录注册, sha1 对称加密  1.des:Data Encryption Standard,数据加密标准  2.aes: ...

  2. 隐私计算加密技术基础系列(下)对称与非对称加密的应用场景

    本章是<隐私计算加密技术基础>系列文章的最后一篇,感慨下,终于写完了,这个春节假期除了陪家人就是写着三篇文章了.其实写之前并没有觉得是多么难的事情,感觉这些原理自己都比较清楚,但是随着写的 ...

  3. 加密算法(摘要算法,对称、非对称加密算法)

    加密目前已经成为计算机安全研究的主要方向,一个密码系统的安全性主要在于密钥的保密性,而不是算法的保密性. 加密系统至少要包括如下四个部分 1 未加密的报文,也叫明文:用M(消息)或P(明文)表示,可以 ...

  4. 快速了解常用的非对称加密算法,再也不用担心面试官的刨根问底

    面试官:说一说你常用的加密算法有哪些? 加密算法通常被分为两种:对称加密算法和非对称加密算法.其中,对称加密算法在加密和解密时使用的密钥相同:非对称加密算法在加密和解密时使用的密钥不同,分为公钥和私钥 ...

  5. iOS - 加解密(对称,非对称)(AES DES base64这里都有),数字签名,cookie

    这篇文章不是研究性的东西,主要是简单的一些知识, 开篇如此, 我尽量不让读者失望. 首先罗列一些知识点: 1.加密算法通常分为对称性加密算法和非对称性加密算法:对于对称性加密算法,信息接收双方都需事先 ...

  6. Mac下python3配置opencv3 3和Mac下单独opencv的配置以及iOS下配置opencv

    #1.Mac下python3配置opencv3.3 新手受任开发一个功能,需要用到opencv.但python和opencv连接出现问题,看了大概有上百份博客的解决办法,都没有解决,快要放弃了,解决了 ...

  7. JAVA加密解密→术语、密码分类、OSI与TCP/IP安全体系、Base64、消息摘要算法MD/SHA/MAC、对称加密算法DES/AES/PBE、非对称加密算法DH/RSA/EIGamaI

    术语 密码分类 OSI与TCP/IP安全体系 JAVA安全 Base64算法 消息摘要算法MD 消息摘要算法MD图解 消息摘要算法SHA 消息摘要算法SHA图解 消息摘要算法MAC 消息摘要算法MAC ...

  8. 如何在没有 Mac 的情况下使用 Flutter 和 Codemagic 构建和分发 iOS 应用

    如果您在 Linux 或 Windows 上工作,请从这篇文章中了解如何构建和发布 iOS 应用程序.我们将展示如何使用 Flutter 和Codemagic(https://flutterci.co ...

  9. 可逆与不可逆算法,对称加密与非对称加密算法总结

    文章目录 1. 加密算法的种类 2. 不可逆加密算法 ①:MD5 ②:HMAC系列 ③:SHA系列 3. 可逆加密算法 1. 对称加密 ①:DES ②:3DES ③:AES 2. 非对称加密 ①:RS ...

最新文章

  1. ORB_SLAM2概述
  2. php获取ip几种方法区别,php获取客户端IP地址的几种方法
  3. Advanced Linq - Dynamic Linq query library: Add support for 'Contains' extension
  4. localdatetime获得时间搓_得用户者得天下,一禅小和尚×往事若茶如何获得消费者认同...
  5. Java黑皮书课后题第5章:5.13(求满足n的三次方<12000的n的最大值)使用while循环找出满足n的三次方<12000的n的最大值
  6. “数据中国”路在何方?答:在“数据中国加速计划”
  7. mysql mysqld.sock_MySQL笔记-最简单的方法来解决找不到mysqld.sock文件的问题
  8. VMware:虚拟机(xp)与主机(win10)连接步骤(超详细)
  9. 关于在线答题系统设计的一些想法
  10. Linux 磁盘操作管理
  11. 中英文常用标点符号统一清洗为英文格式
  12. 港科夜闻|香港科大(广州)系统枢纽署理院长李世玮教授成为首位获电子封装领域最重要荣誉大奖的中国科学家...
  13. 操作系统考研复试、工作面试常见问题及答案
  14. stm32f103系列开发板控制对数码管来显示自定义时间(自主学习)
  15. Java mysql获取行数_java – MySQL查询获取球体中的行(X,Y,Z坐标)?
  16. 易诚互动在创业板更新招股书:上半年出现亏损,极其依赖阿里云
  17. Java软件工程师 (职业简介)
  18. tiny4412开发板实现uboot引导启动android 5.0.2系统
  19. U9 实体操作API参考手册
  20. c#读取mdb文件(c#连接ACCESS数据库)

热门文章

  1. 基于HTTP Live Streaming(HLS) 搭建在线点播系统
  2. Tom's Classes
  3. Python 继承标准类时发生了什么
  4. MSP430常见问题之FLASH存储类
  5. 远程管理客户端--SCCM
  6. 动态为程序指定快捷键
  7. Python 进阶之路 (十二) 尾声即是开始
  8. Deno 兼容浏览器具体指的是什么?
  9. 【自用】 sklearn 用 train_test_split 简单划分训练和测试集
  10. BZOJ 1924 [Sdoi2010]所驼门王的宝藏