使用Swift加密RSA/ECB/OAEPWithSHA-256AndMGF1Padding

8

提前声明,我对密码学不太了解(仅限基础知识)。我正在试图实施一个凭据开放式家居服务,并想要加密密码并将其发送到设备。

设备提供了一个用C语言编写的函数,返回一个公钥字符串,格式如下:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzjFGuEKD0uWxzb47oRbiSP2uDwVJPeWU7m9VXi626V6lameTzdtwj2eYVZTIAsAW7yW4or2skn7oHqFG4GvhMzgMwoQjKFxeCPPFXRSotnt26AN1DhvFJp3V/d+MpmkzI07iWcD5eNe4EVNK9GSE4JOEHhJ/JYBVMiu04XE5aqwIDAQAB

Android的实现已经完成,给定的规格如下:

RSA/ECB/OAEPWithSHA-256AndMGF1Padding

此外,有一个网站提供了加密指南:

http://wiki.openhome.org/wiki/Av:Developer:CredentialsService

到目前为止,我已经尝试了以下库:

SwiftyRSA、Heimdall、SwCrypt

我认为我的主要问题之一是我不理解我拥有什么,我需要什么,最终如何使用Swift实现。

理想情况下,最终我将拥有以下函数:

func encryptMessage(message:String, whithPublicKey key:String)->String

非常感谢您。

不确定您的错误或障碍是什么!该过程看起来需要获取服务器共享的公钥,使用ECB块密码和OAEP填充生成密码的加密消息,并将其发送回服务器。OAEPWithSHA-256AndMGF1Padding 是相当不寻常的,因此请检查哪些库支持它。 - carbonr
公钥由服务器提供。因此我认为服务器有一个用于解密消息的私钥。我想知道如何使用提供的公钥和规格加密消息。 - Reimond Hill
我迄今为止尝试过这些库……还有什么问题?你其中一个尝试的代码在哪里? - President James K. Polk
使用密钥进行加密 - President James K. Polk
看一下使用算法rsaEncryptionOAEPSHA256SecKeyCreateEncryptedData。如果它能够直接使用并且你知道如何使用它,那很好。 如果需要更多帮助,则超出了我在StackOverflow答案中所能做的范围,可能需要在iOS上编写非平凡代码(许多加密算法仅在macOS上受支持)。 如果没有其他人可以指导你完成它,并且你有一些预算,我很乐意讨论咨询协议。请注意,这里的标准算法是SHA-1,并且得到了更广泛的支持。如果可以更改服务器,那可能会对您有所帮助。 - Rob Napier
asn1ParsingFailed 是我遇到的错误之一。 - Reimond Hill
1个回答

11

经过长时间的研究,我刚刚实现了自己的解决方案,而不是使用库并不理解其中的情况。了解发生的事情总是很好的,而在这种情况下并不是特别复杂。

在iOS上,如果您想要加密/解密,您需要使用存储在密钥链上的密钥。如果在我的情况下,我已经收到了公钥,我可以导入它,并且我也可以对私钥执行相同的操作。请查看我的HelperClass 这里

然后,仅限iOS 10及以上版本,您可以调用这两个方法进行加密和解密。

        let error:UnsafeMutablePointer<Unmanaged<CFError>?>? = nil
        let plainData = "A Plain text...".data(using: .utf8)
        if let encryptedMessageData:Data = SecKeyCreateEncryptedData(publicSecKey, .rsaEncryptionOAEPSHA256, plainData! as CFData,error) as Data?{
            print("We have an encrypted message")

            let encryptedMessageSigned = encryptedMessageData.map { Int8(bitPattern: $0) }
            print(encryptedMessageSigned)
            
            if let decryptedMessage:Data = SecKeyCreateDecryptedData(privateSecKey, .rsaEncryptionOAEPSHA256, encryptedMessageData as CFData,error) as Data?{
                print("We have an decrypted message \(String.init(data: decryptedMessage, encoding: .utf8)!)")
            }
            else{
                print("Error decrypting")
            }

        }
        else{
            print("Error encrypting")
        }

此外,如果您使用的是 iOS 10 之前的版本,则可以使用以下功能:

func SecKeyEncrypt(_ key: SecKey, 
             _ padding: SecPadding, 
             _ plainText: UnsafePointer<UInt8>, 
             _ plainTextLen: Int, 
             _ cipherText: UnsafeMutablePointer<UInt8>, 
             _ cipherTextLen: UnsafeMutablePointer<Int>) -> OSStatus

而且

func SecKeyDecrypt(_ key: SecKey, 
             _ padding: SecPadding, 
             _ cipherText: UnsafePointer<UInt8>, 
             _ cipherTextLen: Int, 
             _ plainText: UnsafeMutablePointer<UInt8>, 
             _ plainTextLen: UnsafeMutablePointer<Int>) -> OSStatus

但是这些选项较少且受到相当多的限制。

值得一提的是,我的公钥和私钥是在Android上生成的。

public static String createStringFromPublicKey(Key key) throws Exception {
  X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
  return new String(Base64.encode(x509EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8");
}

以及

public static String createStringFromPrivateKey(Key key) throws Exception {
  PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
  return new String(Base64.encode(pkcs8EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8");
}

你在使用哪种密钥格式来进行安卓开发?是 .Der 还是 .Pem 还是 .BKS?谢谢。 - PPShein
我没有为安卓编写代码。我被给予了公钥字符串... PKCS1 给你更多线索吗? - Reimond Hill
1
我已经尝试了您的代码并运行在Java上,发现了“BadPadding”错误。 - PPShein
private static String createStringFromPublicKey(Key key) throws Exception { X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded()); return new String(Base64.encode(x509EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8"); }私有静态字符串createStringFromPrivateKey(Key key)throws Exception { PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded()); return new String(Base64.encode(pkcs8EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8"); } - Reimond Hill
我需要将publicSecKey转换为SecKey吗? - vaibby
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接