My iOS application creates a key using AES encryption and send it with all the APIs , and it is being decrypted at the server end, now after the update of OS 13.4 the key created from the device(not the simulator) is in incorrect and the following error is thrown by the server :
"Padding is invalid and cannot be removed."
It is working perfectly in the devices below 13.4 OS version , we are using CommonCrypto to encrypt the key at our end , following are the details :
let ivData = "passpharse".data(using:String.Encoding.utf8)!
let cryptLength = size_t(data.count + kCCBlockSizeAES128)
var cryptData = Data(count:cryptLength
let keyLength = size_t(kCCKeySizeAES128)
let options = CCOptions(kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
The surprising part is that the key is being correctly generated for some API calls although same method is used for key generation.
Users with iOS - OS less than 13.4 are not facing any issue, If anyone have came across the same situation please guide.
thanks in advance.
After much research I made it work on all the versions.
if in the above code “passphrase” is shorted than 16 bytes, it uses whatever's in-memory past the end.
It seems like improper use of the CommonCrypto APIs was the issue here. Really don’t know why this worked before, but maybe we got lucky with the memory layout but the issues above need to be remedied before this will function as expected.
Related
I'm trying to create Curve25519 keys using the KeyChain on iOS. I am aware of the existence of CryptoKit, unfortunately, that is not available for iOS 12. Is there a way to create a Curve25519 key pre CryptoKit, maybe a parameter I'm missing when generating it in the KeyChain? The code below will only generate the P-256 keys.
let attributes: [String: Any] = [
String(kSecClass): kSecClassKey,
String(kSecAttrKeyType): kSecAttrKeyTypeECSECPrimeRandom,
String(kSecAttrKeySizeInBits): 256
]
var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)
print(privateKey ?? error!.takeUnretainedValue())
Apple's old core crypto lib CommonCrypto doesn't support modern curves like curve25519 and quite frankly is a total mess, littered with insecure ciphers, they aren't even clear on the actual curve equations being used.
Additionally, although CryptoKit supports curve25519 for key exchange, it's still limited, for example, you cannot use the "Secure Enclave" to generate curve25519 keys, only P-256, which is likely backdoored (just look at the curve co-efficients), despite all financial institutions seemingly loving it.
Ultimately a curve25519 private key is just a large (2^256) number (though it is "clamped" before use), so if you just need to generate keys, you can do this with SecRandomCopyBytes.
Though, if as I suspect you want to do some X25519 KEX or EdDSA signature over 25519, then just use libsodium. It's the goto library for NaCl, there is a really great interface in Swift written by the original libsodium author, called swift-sodium, I've used it and it's great. It also supports iOS 12+.
Generating keys in libsodium for curve25519 is as simple as:
import Sodium
let sodium = Sodium()
let curve25519KeyPair = sodium.box.keyPair()
let privateKey = curve25519KeyPair!.secretKey
let publicKey = curve25519KeyPair!.publicKey
You can then manually store in KeyChain.
Shout if you need further help, and good choice using 25519.
I have an app which uses AES256 decryption for authentication. For this I use the Crypto Swift library.
Until now it always worked, but with iOS 13 coming out, the decryption does not work.
Here's the code I use for decryption:
func aesDecrypt(key: String) throws -> String {
let data = Serializer.hexaToBytes(self)
let key = Serializer.hexaToBytes(key)
let decrypted = try! AES(key: key, blockMode: ECB(), padding: .pkcs7).decrypt(data)
let decryptedData = Data(decrypted)
return String(bytes: decryptedData.bytes, encoding: .utf8) ?? "Could not decrypt"
}
String(bytes: decryptedData.bytes, encoding: .utf8) always returns nil...
Why could that be and what should I do to make it working again?
Any help would be appreciated :)
The most common cause of these kinds of problems is that somewhere you're using Data.description to compute a hex string. That was never correct, but it was possible to get away with it prior to iOS 13. In iOS 13, the format was changed (the format was never promised to stay the same), and that's broken lots of things that relied on it being stable.
The next thing I'd check is Serializer.hexaToBytes to make sure it's correctly implemented and returning what you expect.
Given that this particular function is written in way that doesn't carefully check for errors (and uses a very dangerous mode like ECB), it likely that related functions are similarly uncareful with errors. Check each to see if it's returning the values you're expecting.
When using childByAutoId, something really strange happens. Instead of getting a unique id, I get the following key every time:
-------------------0
I know keys are generated with client side timestamps, so I tried running my code through the iOS simulator and an actual device, same result though.
I don't do anything interesting in my code, but here it is for reference:
func sendRandomMessage() {
let firebaseRootRef = Firebase(url:firebaseRootUrl)
let newMessageRef = firebaseRootRef.childByAutoId()
println(newMessageRef.key)
}
I'm using Firebase 2.3.0
There was a bug in the Firebase SDK for iOS 2.3.0 that caused this problem.
It has been fixed in 2.3.1. See https://www.firebase.com/docs/ios/changelog.html
Is there any way to turn a string into a block of code? I'm making an Ajax request to a website of mine that has an endpoint that returns some swift code as a string. I can get that code back as a string, but I can't run that code because it doesn't know that it is code.
As others have pointed out, if you are creating an iOS app (especially for distribution on the app store), you can not do this. However, if you are writing Swift code for an OS X machine AND you know that XCode is installed on the machine, you can run your Swift code string by running the command-line Swift compiler. Something like this (with proper error checking, of course):
var str = "let str = \"Hello\"\nprintln(\"\\(str) world\")\n"
let task = Process()
task.launchPath = "/usr/bin/swift"
let outpipe = Pipe()
let inpipe = Pipe()
inpipe.fileHandleForWriting.write(str.data(using: String.Encoding.utf8, allowLossyConversion: true)!)
task.standardInput = inpipe
task.standardOutput = outpipe
task.launch()
task.waitUntilExit()
task.standardInput = Pipe()
let data = outpipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
Again, this is probably not recommended in nearly all real-world cases, but is a way you can execute a String of Swift code, if you really need to.
No, you can't do that. Swift is a compiled language, not interpreted like Ajax.
The Swift compiler runs on your Mac, not on the iOS device. (The same is true for Objective-C).
Plus, Apple's app store guidelines forbid delivering executable code to your apps, so even if you figured out a way to do it, your app would be rejected.
Edit:
Note that with the advent of Swift playgrounds, it is possible to run the Swift compiler on an iPad. Recent high-end iPhones are probably also up to the job, but you'd have to figure out how to get it installed.
As stated above though, Apple's app store guidelines forbid you from delivering code to your apps at runtime.
From what I can tell looking through the various padding values for the SecKeyEncrypt method in Apple's security framework, it does not support OAEP padding with a SHA512 hash digest. In fact, I can't seem to determine if the SecKeyEncrypt method does any sort of hashing/masking of each block during the CBC process.
Herein lies my problem. All my other platforms (PHP, Android, .NET) use RSA with OAEP padding and a SHA512 digest.
For example: In C# we can use BouncyCastle's OaepEncoding class which accepts any Digest and performs the hash/mask operation during the block cipher encryption process. In php, the phpseclib project provides the same functionality.
And finally, my question... can this same functionality be achieved on iOS by somehow using a hybrid of "manual" hashing and using SecKeyEncrypt? Or am I missing something much more obvious here.
Cheers!
EDIT: I think I could probably hash/mask each block by porting the bouncy castle code and then pass the new byte array to SecKeyEncrypt for encrpytion, but that begs the question, does SecKeyEncrypt do that already using some other hashing algo internally?
As of iOS 10.0, the .rsaEncryptionOAEPSHA512 option has been added as a SecKeyAlgorithm.
Swift 4
let attributes: [String: Any] = [ ... ]
let pk = SecKeyCreateRandom(attributes as CFDictionary, nil)!
let pub = SecKeyCopyPublicKey(pk)!
let message = "Encrypt me".data(using: .utf8)!
var error: Unmanaged<CFError>?
let cipherText = SecKeyCreateEncryptedData(pub, .rsaEncryptionOAEPSHA512, message as CFData, &error)
It appears this is not possible native to the Security framework for iOS. I have had a ton of issues getting OAEP RSA encryption to work properly cross platform.
However, I did just hear from a third party library provider, Chillkat, that they are adding support for this. See: http://www.chilkatforum.com/questions/7778/ios-rsa-encryption-using-oaep-sha512
EDIT: I installed Chilkat's library and had it working in minutes.