Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encrypt RSA/ECB/OAEPWithSHA-256AndMGF1Padding Swift

I am going to say in advance i don't know too much about cryptography (Basics only). I am trying to Implement a Credential OpenHome Service and I want to encrypt a password to send it to the device.

The device provides a function written in C that returns a public key String that looks like that:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzjFGuEKD0uWxzb47oRbiSP2uDwVJPeWU7m9VXi626V6lameTzdtwj2eYVZTIAsAW7yW4or2skn7oHqFG4GvhMzgMwoQjKFxeCPPFXRSotnt26AN1DhvFJp3V/d+MpmkzI07iWcD5eNe4EVNK9GSE4JOEHhJ/JYBVMiu04XE5aqwIDAQAB

The Android implementation has been already done and the specs given are

RSA/ECB/OAEPWithSHA-256AndMGF1Padding

also there is a web site that gives "instructions" when encrypting

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

I have tried so far these libraries:

SwiftyRSA, Heimdall, SwCrypt

I really thing that one of my main failures are I don't understand what I have, what do I need and finally how to achieve it using swift.

ideally at the end i will have a functions like

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

thank you very much.

like image 238
Reimond Hill Avatar asked Nov 11 '17 11:11

Reimond Hill


People also ask

How do I use RSA encryption in Swift?

Add the private key to the app keychain, with a random tag. Get a reference on the key using the key tag. Use SecKeyDecrypt to decrypt an EncryptedMessage using the key reference and the encrypted message data. Store the resulting decrypted data to a ClearMessage.

Is RSA ECB secure?

As discussed above, ECB mode leaks information about the plaintext because identical plaintext blocks produce identical ciphertext blocks. A ciphertext should never leak any information about the plaintext used to create it, so ECB mode is insecure and should never be used.


1 Answers

After a long research i have just implemented my own solution rather than using libraries and not understanding what was going on. It is always good to know what happens and it this case it is not rocket science.

On iOS if you want to encrypt/decrypt you need to use a key stored on the keychain. If, in my case, i have been given the public key i can import it and also I can do the same with the private key. Please see my HelperClass Here.

Then, and from only from iOS 10, you can call this 2 methods for encrypting and decrypting

        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")
        }

Also, if you want before iOS 10 you have the functions:

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

And

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

But these give less options and They are quite resticted.

Worth mentioning that my public and private key where generate on android using

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");
}

and

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");
}
like image 158
Reimond Hill Avatar answered Nov 06 '22 21:11

Reimond Hill