CryptoSwift throws invalidKeySize because of base64 encoded aesKey and aesIV - swift

I have a project that retrieve data from API and shows in the app. But API uses AES encryption, I have aesKey and aesIV key and these keys are base64 encoded. I need to encode another string with these keys. To do that I use CryptoSwift library but when I try to use this keys to cipher the string, swift console warns me about invalidKeySize.I tried to decode from base64 to string but it did not work as well. These are the keys for an example;
Key and IV size are AES256, for encryption and decryption I need to use PKCS7 padding type with ECB/CBC block mode
aesKey = lHLBfVxlGoKoaCqWORJEHh3jOvC2EBx2VHGyNAdqYV0=
aesIV = 2spaSfljZ/cunRbuVkdphQ==
and CryptoSwift code block is:
let aes = try AES(key: "\(aesKeyString)", iv: "\(aesIVString)")
let cipherText = try aes.encrypt(Array("all".utf8))

The aesKey and aesIV from the snippet is Base64 encoded, so it's not really useful in that form. The convenience initializer you used is for a String, not base64 encoded data that you provided (that happened to be string, but it's different).
let aesKey = "lHLBfVxlGoKoaCqWORJEHh3jOvC2EBx2VHGyNAdqYV0="
let key = [UInt8](base64: aesKey)
let aesIV = "2spaSfljZ/cunRbuVkdphQ=="
let iv = [UInt8](base64: aesIV)
let aes = try AES(key: key, blockMode: CBC(iv: iv))
let cipherText = try aes.encrypt(Array("all".utf8))

Related

iOS CryptoKit AES-GCM is it possible to use a nonce with fewer than 12 bytes?

I am attempting to interface with an existing device that uses AES-GCM with a 4-byte nonce (UInt32). This is a simple incremental counter that increases each time an operation occurs:
var cryptoCounter: UInt32 = 0
I then attempt to encrypt it and retrieve the values like so:
let key = SymmetricKey(data: sharedKey) // This is a 32-byte key.
let nonceData = withUnsafeBytes(of: cryptoCounter.bigEndian, Array.init) // Convert UInt32 to 4-byte data.
let nonce = try! AES.GCM.Nonce(data: Data(nonceData)) // This throws an invalid parameter size exception.
let encrypted = try! AES.GCM.seal(serialized, using: key, nonce: nonce)
However, the AES.GCM.Nonce doesn't work with fewer than 12 bytes, so the 4-byte nonce causes it to throw an error. I've tried padding the nonce with a spare 0'ed 8-bytes:
let nonceData = [0, 0, 0, 0, 0, 0, 0, 0] + withUnsafeBytes(of: cryptoCounter.bigEndian, Array.init)
But the encrypted value is rejected by the device, so I assume this isn't correct. If anyone has any suggestions on the best way to implement this Swift, that would be amazing! Thank you.
I figured out a solution that worked for me.
I used the excellent CryptoSwift library (7.8k stars on GitHub at time of writing):
let gcm = GCM(iv: withUnsafeBytes(of: cryptoCounter.bigEndian, Array.init), mode: .detached)
let aes = try! AES(key: [UInt8](sharedKey), blockMode: gcm, padding: .noPadding)
let encrypted = try! aes.encrypt([UInt8](serialized))

How to convert RSA pem file to XML in swift? or How to get RSA XML in swift?

I have a project on who want to generate a public and private key with RSA and I use SwiftyRSA, but it just can export PEM, base64 and data format. Now how can I convert those formate to XML?
do {
let keyPair = try SwiftyRSA.generateRSAKeyPair(sizeInBits: 2048)
let privateKey = keyPair.privateKey
let publicKey = keyPair.publicKey
print("pemString:==============\npr-> \(try! privateKey.pemString())")
print("base64String:==============\npr-> \(try! privateKey.base64String())")
print("data:==============\npr-> \(try! privateKey.data())")
} catch {
print("error -> No key generated")
}
The XML file is simply a text with some structure. In your case it's:
<RSAKeyValue>
<Modulus>
...
</Modulus>
<Exponent>
...
</Exponent>
</RSAKeyValue>
So you can simply extract modulus and exponent from string returned by pemString() and put it in your XML template.
Can I get the modulus or exponent from a SecKeyRef object in Swift?

Conversion from String to binary and then to base64 format

Trying to create a signature by using RFC 2104-compliant HMAC with the SHA256 hash algorithm. I am half-way done but stuck in converting a string to binary and then to base64 format.
Here is the instruction I am following.
Here is the code I made
let stringToSign = "GET\nwebservices.amazon.com\n/onca/xml\nAWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&AssociateTag=mytag-20&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers%2CReviews&Service=AWSECommerceService&Timestamp=2014-08-18T12%3A00%3A00Z&Version=2013-08-01"
let beforeCoversion = stringToSign.hmac(algorithm: .SHA256, key: "1234567890")
let binary = beforeCoversion.data(using: .utf8, allowLossyConversion: false)
let afterCoversion = binary?.base64EncodedString(options: [.lineLength64Characters])
print(beforeCoversion)
print(afterCoversion!)
Print
8fb6d93342d767d797799aee4ea5a6d8322f0d8554537c313cfa69fa25f1cd07
OGZiNmQ5MzM0MmQ3NjdkNzk3Nzk5YWVlNGVhNWE2ZDgzMjJmMGQ4NTU0NTM3YzMx
M2NmYTY5ZmEyNWYxY2QwNw==
I can see that I get 8fb6d93342d767d797799aee4ea5a6d8322f0d8554537c313cfa69fa25f1cd07 so my conversion is failed in converting a string to binary and then to base64 format. I believe beforeCoversion.data(using: .utf8, allowLossyConversion: false) can be used for converting a string to binary and binary?.base64EncodedString(options: [.lineLength64Characters]) can be used for converting to base64 format. Is that correct? sAny suggestions?
Easy way to solve this if you use amazon-api
pod 'AWSAPIGateway'
Then
let dataToSign = stringToSign.data(using: String.Encoding.utf8)
let conversion = AWSSignatureSignerUtility.hmacSign(dataToSign, withKey: "1234567890", usingAlgorithm: UInt32(kCCHmacAlgSHA256))!
Thanks Roozbeh Zabihollahi for the answer in Amazon Product Advertising API Signature in iOS

How to do aes-ccm encryption in Swift 3

I need to encrypt and decrypt in Swift 3 by using AES-CCM.
I have installed module CryptoSwift, and my app is ok to do normal AES128 like this:
//aes
let input: Array<UInt8> = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]
let key: Array<UInt8> = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]
let iv: Array<UInt8> = AES.randomIV(AES.blockSize)
do {
let encrypted = try AES(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7).encrypt(input)
print(encrypted)
let decrypted = try AES(key: key, iv: iv, blockMode: .CBC, padding: .pkcs7).decrypt(encrypted)
print(decrypted)
} catch {
print(error)
}
But I cannot find a way to do CCM mode which there is no IV but a nonce shorter than 16 bytes.
Is CryptoSwift able to do AES-CCM or do I have to look for other modules?
Please give me some suggestion.

Swift Sodium - Anonymous Encryption (Sealed Boxes)

I am trying to encrypt value using swift sodium with given public key.
However, the encrypted value is not the same as what's produced on server side.
I am not sure whether this piece of coding is right in swift.
The steps are similar to how its done in java.
Assume public key is in base64 string format.
Java:
String pubKey = "w6mjd11n9w9ncKfcuR888Ygi02ou+46ocIajlcUEmQ=";
String secret = "hithere"
byte[] pubKeyBytes = Base64.decode(pubKey,0);
SealedBox sealedDeal = new SealedBox(pubKeyBytes);
byte[] c = sealedDeal.encrypt(secret.getBytes());
String ciphertext = Base64.encodeToString(c, 0);
Swift:
let pubKey = "w6mjd11n9w9ncKfcuR888Ygi02ou+46ocIajlcUEmQ="
let dataDecoded:NSData = NSData(base64Encoded: pubKey, options: NSData.Base64DecodingOptions(rawValue: 0))!
let secret = "hithere".toData()!
let c : Data = sodium.box.seal(message: secret, recipientPublicKey: dataDecoded as Box.PublicKey)!
let ciphertext = c.base64EncodedString(options: .init(rawValue: 0))
Please tell me know what's wrong with the swift equivalent coding.
Thanks alot.
The encrypted value is supposed to be different, so that ciphertexts resulting from equivalent plaintexts are indistinguishable (see Ciphertext indistinguishability).
sodium.box.seal internally generates new nonce every time you are encrypting message, #Max is right, this is normal behave
You can use Detached mode to give same nonce, but this is a very bad idea
In your example you have used Anonymous Encryption I suggest you to take a look at Authenticated Encryption