1
votes

I have a swift app that uses a RSA public key to send data to a python server, and have the server decrypt it with the server private key. However, swift returns a different cipher text each time. Is there any way to have it not salt it?

I've tried using SwiftyRSA, and SwiftUtils to implement the encryption, and while asking others for help, it seems swift automatically salts the message.

override func viewDidLoad() {
    ....
    do{
        let data = "\(message!)".data(using: String.Encoding.utf8)!
        // tag name to access the stored public key in keychain
        let TAG_PUBLIC_KEY = "com.example.keyPublic"
        let encryptStr = "encrypted_message="
        let encryptStrData = encryptStr.data(using: String.Encoding.utf8)!
        let keyString = getKeyStringFromPEMString(PEMString: """
-----BEGIN PUBLIC KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END PUBLIC KEY-----
""")
        let encryptedData = try RSAUtils.encryptWithRSAPublicKey(data: data, pubkeyBase64: keyString, tagName: TAG_PUBLIC_KEY)!
        let length = encryptStrData.count + encryptedData.count
        var array = [UInt8](repeating:0, count:length)
        encryptStrData.copyBytes(to: &array, count: encryptStrData.count)
        encryptedData.copyBytes(to: &array+encryptStrData.count, count: encryptedData.count)
        var st=""
        for byte in encryptedData{
            st += String(format:"%02X", byte)
        }
        print("ENCRYPTED MESSAGE")
        print(st)
    }
    catch{
        print(error)
    }
    ...
    //Key function - remove header and footer
    func getKeyStringFromPEMString(PEMString: String) -> String {
        let keyArray = PEMString.split(separator: "\n") //Remove new line characters
        var keyOutput : String = ""
        for item in keyArray {
            if !item.contains("-----") { //Example: -----BEGIN PUBLIC KEY-----
                keyOutput += item //Join the text together as a single string
            }
        }
        return keyOutput
    }
    ....
}
from Crypto.PublicKey import RSA
from Crypto import Random
from base64 import b64decode
def decText(encTest):
    random_generator = Random.new().read
    key = RSA.generate(2048, random_generator)
    with open('private.pem','r') as f:
        key=RSA.importKey(f.read())
    rawCipherData = b64decode(encTest)
    decrypted = key.decrypt(encTest)
    print(decrypted)
    return decrypted

Here's the plaintext. 33ba884d57161df955de45c50e3bba69c83233402bf460906b919bc0806b44356112b6e0b8dd8f2f5804d5b527e996ba91e91015915f03d0292d89b7ecfc3c44

And here's the ciphertext
0C344863CBC6A4D9153C275DE2074C097A153BFBFD2A34F5312FED4BB075FF28DC3CC584A31CBBD1DCCBBFC18417C1B624B9312F67703817B478DBD07A59CD59E62831A833F5ECA07A94C7E55DB59C4F204FA92DEA4C79106FFA66427B8D49ECAC0E962F8466A7BD525624339DC96ABF0D6130113A8A00C0F3581DD87C234667AE3480B8DFD172B54CB0D50CE9F1BCCB5102EF780F3E2C0C6AC9D53D00B8BAF69850E832C9B6A5D324BE6DC8D059D2F123D0D5A89D2BEFAE1D5202D25F558D47821875CAFDAC733A45F53DEFA69CCDD12D50005914E6105C5C055CC4531822862A5A581D0D5FF1EE593A168390319D2466AB0A939C546DAF919979A177FB4288

Here's the hex of what python outputs with this cipher text: A8 AB FA EF FE 71 7E 3E 19 C0 02 AC 08 7E 0C 0C 01 50 A6 34 85 E2 F1 6D 36 DD 30 B2 FA BC A0 64 B8 C2 A0 3E 40 A7 9A A3 C7 05 E1 55 AD CE 61 64 33 0A 89 30 A4 86 55 74 43 F3 3F 37 45 B6 AC 81 27 26 41 B1 69 A3 0A FC 30 38 5A 03 7D 86 45 55 9F 5C 6A 12 E7 0C 8D 06 0E 84 48 1F 25 F6 0E CD 22 3A E2 DC AE C6 0B 51 F1 C4 52 66 99 49 2F EC E4 48 A1 50 D9 FC 93 5B BC E1 D2 E4 5F CF 83 77 2E D5 87 67 08 3E 80 0B AF 9B 6E 30 37 50 61 0E 21 9E DB 6A A0 01 93 D4 C8 9D EF E9 27 BD BB 36 2F 07 FA 9C 5F D3 42 23 42 48 00 35 B0 11 24 DD 45 83 D1 C2 80 2D B1 B3 DF E7 9E D3 90 2F 60 C7 14 25 20 28 73 BC AB 6E 75 15 27 22 C2 C9 B3 E0 46 1D C2 99 C5 85 E8 F5 D4 D2 A3 1E 5A 59 42 3B FC 2B 48 E4 49 0A 6C 1D D1 2F 27 D3 CF 75 63 41 C5 5A 26 BC 56 EB A3 28 59 A4 32 61 82 A4 2E 41

1
The RSA padding has a random part so it is correct that the encryption returns a randomized ciphertext. Without the padding the RSA is seriously unsecuregusto2
So how should I fix this? Is there a way to have python handle this issue?trainboy2019
There is nothing to fix, it is so by design and you should not change it (you can implement your own RSA encryption with static padding, but I strongly voice against such foolishness). Event the ciphertext is randomized, it will decrypt the the same plaintext. Maybe if you update your question and explain why you want to have static output, someone could help you achieve your goal (even other way)gusto2
What the key issue is is that the python script won't decrypt the ciphertext. That's the issue I was referring to. It will not decrypt the ciphertext back to plaintexttrainboy2019
what exception do you receive? in the python script - do you cut off the prepended text encrypted_message=? I see the swift code is doing hex encoding, but python base64 decodinggusto2

1 Answers

1
votes

I see difference in encoding and decoding

in the Swift encryption code the encryption seems to output:

hex_encode( "encrypted_message=" + encrypt( data ) )

while the python is doing

base64_decode( ciphertext )

If there's something else, you will need to provide working and verifiable code sample, inputs you use and exception you get