【问题标题】:RSA encryption/decryption implementing in Swift from Android Java code从 Android Java 代码在 Swift 中实现的 RSA 加密/解密
【发布时间】:2021-08-06 12:29:26
【问题描述】:

我有这些 Java 方法需要在 Swift 中实现:

    fun encryptMessage(content: String): String {
        val cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING")
        cipher.init(Cipher.ENCRYPT_MODE, publicKey)
        val encryptedBytes = cipher.doFinal(content.toByteArray())
        val encryptedData = Base64.encodeToString(encryptedBytes, Base64.DEFAULT)
        return ENCRYPT_MARK + encryptedData
    }
​
    fun decryptMessage(content: String): String {
        val cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING")
        cipher.init(Cipher.DECRYPT_MODE, privateKey)
        var encryptedData = Base64.decode(content.substring(ENCRYPT_MARK.length), Base64.DEFAULT)
        val decryptedBytes = cipher.doFinal(encryptedData)
        return String(decryptedBytes)
    }

我不是很擅长加密和解密。 我尝试了几个我找到的库和代码,但没有一个对我有用。

我需要解密的示例字符串:

"p+KuB7UVUteY8g3HVMxo+7h2xhZQxhPjPayMolqq8EYyIknbQjgqHjC95NR8/le6G0F8SQACrOdj\nTlPU1+o7bZrE8ukI7B35i9sWZns3Y2scA9U7yz8z5KsTZ240+4+Xd7dZwfQ49Z6J7nNOfBR/97pq\n2l1QKe0/SThUEraZyts=\n"

我的私钥:

"-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDjOUZOZgIYWDMkyhyNb/gsFUDbDB3a+FWwT0d2HE7cd3bqebYLg\nKAMqwpc8nCHR77kO23Nd/U5WKVWwFcHUQVtkMcX4QNDtxSV72LRNaSaQZkwBofw9O\nu338mm1hR0DEYzYPXKuyaP3l5/pvZyvOHrA+i0ZD7pUohEtiDsuNhZbwIDAQABAoG\nBAJoM6q2cWy9GHOaEYHdDwm2guyfHPzaFxxKRrVFWP+EY3XZ6rgF+YwQzsgLyG3ic\nG7+AyyDSg18tymrWXCqJs7Mdrxq3xZmdCzwTcfgxZcwiFG0caK/jbA8rXO60xecag\nZRR+AyWa+2wnwt5xPtFcqk7GhqkWIolzQddW7L3CIuBAkEA9Xw+fnLrbR3WaxTpa3\n88NEEgvyxIS2eGc+lRUbC8w2xX5qDtV8Ak7rxkmXGURJ6tvwyUi/Q+5y+X20mBtt8\nsKwJBAOz0yph9n4iHtC+BL5U+LfpZuUO6uUctbmfXs+fU2glI8rAwXhanBCs0Ph/0\nG7aXmNKHvcSjQ9N5mhTPBvhpcc0CQH4PPTBF5ytzZQY8CNmQzuOuhhhlrwI5uUuQh\npfCgEyCOGlQPlEPdGe8CpTZRGAwc9xlo2pzFFI3mG2dQ6Ua2V0CQQCSMY11e7wbzi\n37SScEWzKezRCimueI5JzDcK/MjuRe6iThU1YZf73wsfDKYh9fDjT5X0pTsa89ID9\nSK1DPnq7ZAkB6ybvpomovyBBgSjjTEwwSHyAIr5HIE2hkDjer6/87/WNKEw1yg11b\ngSoJC67f1xnLj7bv9/EJRPWTokCaRRm/\n-----END RSA PRIVATE KEY-----"

1. SecKeyCreateDecryptedData

let encryptedMessageData = encryptedMessage.data(using: .utf8)
if let decryptedMessage:Data = SecKeyCreateDecryptedData(privateSecKey!, .rsaEncryptionPKCS1, encryptedMessageData as CFData, error) as Data? {
    print("We have an decrypted message \(String.init(data: decryptedMessage, encoding: .utf8)!)")
} else {
    print("Error decrypting")
}
  • 不工作。我得到打印“错误解密”但变量中没有错误

2。 SwiftyRSA

    let encrypted = try EncryptedMessage(data: key.data(using: .utf8)!) // try EncryptedMessage(base64Encoded: key)
    
    let privateKey = try PrivateKey(pemEncoded: keyPair.privateKey)
    let decryptedKey = try encrypted.decrypted(with: privateKey, padding: SecPadding.PKCS1)
  • 出现 chunkDecryptFailed(index: 0) 错误。

3. CryptorRSA

    let data = base64.data(using: .utf8)!
    let encryptedData = try CryptorRSA.createEncrypted(with: data)
    let decryptedData = try encryptedData.decrypted(with: privateKey, algorithm: .sha1)
  • 出现错误:

    Error Domain=NSOSStatusErrorDomain Code=-50 "RSAdecrypt 错误输入 (err -27)" UserInfo={numberOfErrorsDeep=0, NSDescription=RSAdecrypt 错误输入 (err -27)}

我什至尝试用这些代码行来实现解密,但没有运气:

static func decrypt(string: String, privateKey: String?) -> String? {
    guard let privateKey = privateKey else { return nil }
    
    let keyString = privateKey.replacingOccurrences(of: "-----BEGIN RSA PRIVATE KEY-----\n", with: "").replacingOccurrences(of: "\n-----END RSA PRIVATE KEY-----", with: "")
    guard let data = Data(base64Encoded: keyString, options: .ignoreUnknownCharacters) else { return nil }
    
    var attributes: CFDictionary {
        return [kSecAttrKeyType         : kSecAttrKeyTypeRSA,
                kSecAttrKeyClass        : kSecAttrKeyClassPrivate,
                kSecAttrKeySizeInBits   : 2048,
                kSecReturnPersistentRef : true] as CFDictionary
    }
    
    var error: Unmanaged<CFError>? = nil
    guard let secKey = SecKeyCreateWithData(data as CFData, attributes, &error) else {
        print(error.debugDescription)
        return nil
    }
    return decrypt(string: string, privateKey: secKey)
}

static func decrypt(string: String, privateKey: SecKey) -> String?  {
    let buffer = [UInt8](string.utf8)
    
    let keySize = SecKeyGetBlockSize(privateKey)
    var messageDecrypted = [UInt8](repeating: 0, count: keySize)
    var messageDecryptedSize = keySize
    
    var status = SecKeyDecrypt(privateKey, SecPadding.PKCS1, buffer, buffer.count, &messageDecrypted, &messageDecryptedSize)
    
    if status != noErr {
        print("Decryption Error!")
        return nil
    }
    
    let result = String(bytes: messageDecrypted, encoding: .utf8)
    print(result)
    return result
}

我做错了什么?如何解密该示例数据?感谢您的帮助

【问题讨论】:

  • 你有解决办法吗?

标签: ios swift encryption cryptography rsa


【解决方案1】:

您将在下面看到一个使用随机生成的密钥进行加密和解密的快速示例。为简单起见,我添加了 bang 运算符,但它可能只是向您展示如何在 Swift 中使用 RSA 加密和解密数据。

let attributes = [
    kSecAttrKeyType: kSecAttrKeyTypeRSA,
    kSecAttrKeySizeInBits: 2048,
    kSecAttrKeyClass: kSecAttrKeyClassPrivate
] as CFDictionary

var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateRandomKey(attributes, &error)!
let publicKey = SecKeyCopyPublicKey(privateKey)!

let message = Data("Hello World".utf8)

let ciphertext = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, message as CFData, &error)! as Data

print(ciphertext as NSData)

let plaintext = SecKeyCreateDecryptedData(privateKey, .rsaEncryptionPKCS1, ciphertext as CFData, &error)! as Data
print(String(data: plaintext, encoding: .utf8) ?? "Non UTF8")

现在,我们可以使用您的密钥来做同样的事情。您的密钥当前是 PEM 格式。您必须删除页眉、页脚和所有换行符才能将其转换为 DER,iOS 在可能的情况下非常严格。您可以将上面的某些行替换为以下代码。

let keyBytes = Data(base64Encoded: "<your DER encoded bytes>")! as CFData

var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateWithData(keyBytes, attributes, &error)!
let publicKey = SecKeyCopyPublicKey(privateKey)!

所以我只想告诉您,您的密文被弄乱了,或者密文是使用与属于您的私钥的公钥不同的公钥创建的。我猜是第一个,因为我在 base64 字符串中看到了新行...

现在,一些重要的注意事项:

  • 请勿使用您在此处发布的私钥运送您的产品。出于某种原因,它被称为私有密钥
  • RSA 已过时,这在其密钥大小中尤为明显。您不应该使用 1024 位 RSA 密钥,它们不安全。切换到至少 2048 位的密钥
  • 使用public密钥进行加密,使用private密钥进行解密(如示例所示)
  • 使用 RSA 密钥的加密是有限的;只能加密或解密少量数据,而且 RSA 很慢。如果您需要加密大量数据并尽可能快,您可能需要查看 AES 或 ChaCha(尽管它们都是对称算法)

附:您的 DER 编码字符串是:

MIICXQIBAAKBgQDjOUZOZgIYWDMkyhyNb/gsFUDbDB3a+FWwT0d2HE7cd3bqebYLgKAMqwpc8nCHR77kO23Nd/U5WKVWwFcHUQVtkMcX4QNDtxSV72LRNaSaQZkwBofw9Ou338mm1hR0DEYzYPXKuyaP3l5/pvZyvOHrA+i0ZD7pUohEtiDsuNhZbwIDAQABAoGBAJoM6q2cWy9GHOaEYHdDwm2guyfHPzaFxxKRrVFWP+EY3XZ6rgF+YwQzsgLyG3icG7+AyyDSg18tymrWXCqJs7Mdrxq3xZmdCzwTcfgxZcwiFG0caK/jbA8rXO60xecagZRR+AyWa+2wnwt5xPtFcqk7GhqkWIolzQddW7L3CIuBAkEA9Xw+fnLrbR3WaxTpa388NEEgvyxIS2eGc+lRUbC8w2xX5qDtV8Ak7rxkmXGURJ6tvwyUi/Q+5y+X20mBtt8sKwJBAOz0yph9n4iHtC+BL5U+LfpZuUO6uUctbmfXs+fU2glI8rAwXhanBCs0Ph/0G7aXmNKHvcSjQ9N5mhTPBvhpcc0CQH4PPTBF5ytzZQY8CNmQzuOuhhhlrwI5uUuQhpfCgEyCOGlQPlEPdGe8CpTZRGAwc9xlo2pzFFI3mG2dQ6Ua2V0CQQCSMY11e7wbzi37SScEWzKezRCimueI5JzDcK/MjuRe6iThU1YZf73wsfDKYh9fDjT5X0pTsa89ID9SK1DPnq7ZAkB6ybvpomovyBBgSjjTEwwSHyAIr5HIE2hkDjer6/87/WNKEw1yg11bgSoJC67f1xnLj7bv9/EJRPWTokCaRRm/"

【讨论】:

  • 感谢您提供非常详细的回答。问题是所有数据都已设置,我正在尝试实施适用于 Android 的解决方案。所以密文应该是正确的。我必须能够解密它。我是否可以从该字符串中删除新行?还是有另一种方法可以“修复”密文正确/使用私钥?
  • 删除换行符后密文是正确的(128 字节的数据对于 1024 位 RSA 密钥是正确的)。您可以尝试在 iOS 上创建加密数据并尝试在 Android 上对其进行解密,看看是否可行。您可以尝试在 Android 上解密“Hello World”示例
猜你喜欢
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 2012-09-10
  • 2011-12-20
  • 1970-01-01
  • 2023-03-15
  • 2015-02-27
相关资源
最近更新 更多