通过Android Java代码在Swift中实现RSA加密/解密

bogh5gae  于 2023-02-11  发布在  Swift
关注(0)|答案(2)|浏览(237)

我需要在Swift中实现这些来自Java的方法:

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.安全密钥创建解密数据**
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.快速RSA**
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)
  • 获取块解密失败(索引:0)错误。
    • 3.加密算法RSA**
let data = base64.data(using: .utf8)!
    let encryptedData = try CryptorRSA.createEncrypted(with: data)
    let decryptedData = try encryptedData.decrypted(with: privateKey, algorithm: .sha1)
  • 获取错误:

错误域= NSOS状态错误域代码= -50 "RSA解密错误输入(错误-27)"用户信息= {错误深度数= 0,NS描述= RSA解密错误输入(错误-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
}

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

oiopk7p5

oiopk7p51#

下面你会看到一个使用随机生成的密钥进行加密和解密的快速示例,为了简单起见,我添加了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位的密钥
  • 加密使用公钥完成,解密使用私钥完成(如示例所示)
  • 使用RSA密钥的加密受到限制;只有少量的数据可以加密或解密,RSA很慢。如果你需要加密大量的数据,并需要它尽可能快,你可能想检查AES或ChaCha(尽管它们都是对称算法)

P.S.您的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/"
2hh7jdfx

2hh7jdfx2#

示例栏

可能是这个问题(只需为您的私钥对齐它):

  • 为什么来自“Java17 KeyFactory”和Swift(iOS)的PKCS#1公钥不同?

从Android生成的RSA密钥& iOS看起来几乎相同,他们携带基本相同的信息.
还是...

  • Java代码生成SPKI格式的RSA密钥。
  • Swift采用PKCS#1格式的RSA密钥。

. .. ... Base64编码,您可能希望使用以下方法分析密钥:

样品溶液

您可以使用BouncyCastleJava依赖项转换密钥,然后再将其发送到iOS。

相关问题