【问题标题】:Generate an RSA public / private key pair生成 RSA 公钥/私钥对
【发布时间】:2015-10-08 17:06:24
【问题描述】:

我正在寻找在swift 中生成RSA 公钥/私钥对的最简单方法我已经看到很多关于iOS 不支持OpenSSL 的讨论。

我只需要生成密钥对并将公钥发送到我的服务器,服务器将encrypt 一些带有密钥的数据并将其发送回我的私钥到decrypt。这是一次性交易,之后我将不再需要密钥。

对此最简单、最轻便的解决方案是什么?

【问题讨论】:

  • 如果只是在客户端和服务器之间进行传输,为什么不直接使用 HTTPS?
  • @blobbfuesch 我们正在使用 HTTPS,但我的雇主担心它的安全性不够,因此我们正在尝试在 HTTPS 下实现另一个级别。
  • 如果 AES 不够安全,RSA 也不是。在比较密钥的强度时,RSA-1024 的安全性低于 AES-128。 (来源:this answer from the information security sister forum
  • @blobbfuesch 计划是使用 AES 进行以后的交易,但我们将使用 RSA 将密钥从服务器发送到客户端。你有更好的建议吗?
  • 我会使用 HTTPS 进行加密,并使用 4096 位 RSA 进行完美的前向保密。即使服务器密钥被盗,也只有活动会话可以被解密(使用来自客户端的公钥加密数据在这里无济于事)。之前的所有交通都是安全的。

标签: swift swift2


【解决方案1】:

这个 Github 存储库 - Heimdall,应该可以帮助您生成密钥和加密数据。

示例用法:

if let heimdall = Heimdall(tagPrefix: "com.example") {
    let testString = "This is a test string"
// Encryption/Decryption
if let encryptedString = heimdall.encrypt(testString) {
    println(encryptedString) // "cQzaQCQLhAWqkDyPoHnPrpsVh..."

    if let decryptedString = heimdall.decrypt(encryptedString) {
        println(decryptedString) // "This is a test string"
    }
}

// Signatures/Verification
if let signature = heimdall.sign(testString) {
    println(signature) // "fMVOFj6SQ7h+cZTEXZxkpgaDsMrki..."
    var verified = heimdall.verify(testString, signatureBase64: signature)
    println(verified) // True

    // If someone meddles with the message and the signature becomes invalid
    verified = heimdall.verify(testString + "injected false message",
                                signatureBase64: signature)
    println(verified) // False
}

用自己的公钥加密数据:

btnguyen2kswift-rsautils 实用程序应该可以帮助您使用自己的公钥加密数据。使用起来非常简单。

使用方法:

首先只需将RSAUtils.swift 文件拖放到您的项目中。

就是这样!

加密基本字符串:

let PUBLIC_KEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJh+/sdLdlVVcM5V5/j/RbwM8SL++Sc3dMqMK1nP73XYKhvO63bxPkWwaY0kwcUU40+QducwjueVOzcPFvHf+fECAwEAAQ=="

let sampleText:String = "WHATS UP"

let encrypted:NSData? = RSAUtils.encryptWithRSAPublicKey(sampleText.dataUsingEncoding(NSUTF8StringEncoding)!, pubkeyBase64: PUBLIC_KEY, keychainTag: "yourdomain.com")

let encryptedDataText = encrypted!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions())

print(encryptedDataText)

打印如下:

ML5S87dfDB6l1uHFcACm2IdkGHpDGPUaYoSNTO+83qcWYxTEddFeKhETIcqF5n67nRDL0lKi5XV9uEI7hGTyKA==

【讨论】:

  • 我以前看过这个 repo 但我没有看到任何生成密钥的例子?你能提供一个吗?
  • 知道是否可以插入我自己的公钥用于加密?
  • 可能不会,因为那也是不安全的。始终生成新的密钥对。
  • 我能问一下它为什么不安全吗?我的服务器通过它的公钥发送,然后我用它加密我的数据并将其发送回服务器以使用它的私钥解密。
  • 比方说,您硬编码您的私钥,然后使用您自己的与该密钥配合使用的公钥,然后有人可以通过逆向工程(反编译)获得私钥。而且那个键也不会改变。如果您每次启动应用程序或每次安装时都生成新的密钥对,那么密钥将很难被盗。
【解决方案2】:

这是在 Swift 中使用 SecKeyGeneratePair 生成 RSA 密钥对的最简单方法:

        var statusCode: OSStatus
        var publicKey: SecKey?
        var privateKey: SecKey?

        let publicKeyAttr: [NSObject: NSObject] = [kSecAttrIsPermanent:true, kSecAttrApplicationTag:"publicTag".dataUsingEncoding(NSUTF8StringEncoding)!]
        let privateKeyAttr: [NSObject: NSObject] = [kSecAttrIsPermanent:true, kSecAttrApplicationTag:"privateTag".dataUsingEncoding(NSUTF8StringEncoding)!]

        var keyPairAttr = [NSObject: NSObject]()
        keyPairAttr[kSecAttrKeyType] = kSecAttrKeyTypeRSA
        keyPairAttr[kSecAttrKeySizeInBits] = 512
        keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr
        keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr

        statusCode = SecKeyGeneratePair(keyPairAttr, &publicKey, &privateKey)

        if statusCode == noErr && publicKey != nil && privateKey != nil {
            printMessage = "Key pair generated OK"
            print("Public Key: \(publicKey!)")
            print("Private Key: \(privateKey!)")
        } else {
            printMessage = "Error generating key pair: \(statusCode)"
        }

【讨论】: