How to Generate Symmetric AES Key from NSData? - ios

I need to generate a symmetric AES key from NSData value which created below :
let decodedData = NSData(base64EncodedString: initKey, options: NSDataBase64DecodingOptions(rawValue: 0))
(the initKey is a base64 String value.)
the question is how can i generate a secret key from the "decodedData"? (similar to android SecretKeySpec)
(i'm using swift 2.2)
Here is the scenario (in android) :
1- i have a base64 string.
2- i decode it to bytes array.
3- then create a secretkey based on bytes array length and AES type.
4- and finally define a AES cipher based on secretkey, to encode some strings.
thanks for help

An AES key is just 16 or 32 bytes of random data. There's no structure to them. If it's the correct length, you already have a key. If by SecretKeySpec you mean "using PBE" (password based encryption), then it completely depends on what parameters are passed to SecretKeySpec how to recreate that with CommonCrypto. There is no universal standard format for AES encryption. You have to reproduce whatever is being done by the encryptor. So if you're trying to match it, you'll need to explain exactly what is being done.
Thanks to #rob-napier

Related

CX509PublicKeyClass initialize is failing at runtime with WIN32: 13 ERROR_INVALID_DATA

I am trying to populate the CX509PublicKeyClass() object using InitializeFromEncodedPublicKeyInfo(data); where data is from the file id_rsa.pub (KeyFilePath) that I created using ss-keygen client in windows.
Sample code I am tying with
The image also shows the exception that is being thrown.
I suspect the issue could be with the expected encoding
public virtual void InitializeFromEncodedPublicKeyInfo(string strEncodedPublicKeyInfo, EncodingType Encoding = EncodingType.XCN_CRYPT_STRING_BASE64);
and I have tried multiple combinations, Hex and base64 , default string etc but I am still seeing the same error.
The answer lies in understanding RSA key formats
Private key contains: modulus, private exponent, public exponent, prime 1, prime 2, exponent 1, exponent 2 and coefficient
Public key contains: only modulus and public exponent.
PEM format produced by OpenSSL is actually base64 encoded and wrapped key data in the binary format called DER. Thus, to work with PEM format you must actually work with DER.
DER format is based on Abstract Syntax Notation One (ASN.1) standard. The standard specifies the encoding of tree-like data structures. Two predefined data structures are used for private and public RSA keys. Though I didn’t find a good parser for the format, with a couple of notes from the standard in hand I wrote a class for encoding and decoding ASN.1 values.
PEM format contains base64 encoded DER data. It also adds a header and footer to it. Below is an example of PEM file for a private key.

Process to encrypt a 128 bit string [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Ok. I am completely stuck on encryption. Could someone walk me through the process of how to encrypt a string using an AES 128bit key, CBC, PKCS7Padding, base64 format? I am new to encryption so bear with me here. I have posted questions in the past that relate to previous 3rd party libraries but none have worked for me. If someone could provide me sample code and briefly explain the process that would be greatly appreciated. Thanks.
For those who find errors and/or ommisions please either add a commwent and I will revise or edit this post directly.
AES 128bit key, CBC, PKCS7Padding, base64
AES: is an encryption method (Advanced Encryption Standard)
128 bit: the key length in bits (16 bytes).
CBC: an encryption mode (Cipher Block Chaining)
PKCS7Padding: adding bytes to data to be encrypted to make the data an exactly multiple of the block size
Base64: an encoding of 8-bit data into printable characters. Nothing to do with encryption but many times used with encryption
Block: AES encrypts data a block (16 bytes) at a time
iv: a seed value for certain encryption modes including CBC (initialization vector)
Needed for "AES, 128bit key, CBC, PKCS7Padding"
Encryption:
data: 8-bit bytes (any number)
key: 16 8-bit bytes (exactly)
iv: 16 8-bit bytes (exactly)
The encryption uses these inputs to create an encrypted output of 8-bit bytes with a length longer than the input due to padding to create an exact multiple of the block size. This will make the output data at least 1 byte longer than the input.
The output is raw bytes, that is not ASCII or a unicode encoding. In many cases the result must be printable characters and is Base64 encoded to achieve that. Base64 encoding makes the data longer.
Decryption:
If the data is in Base64 format decode it to raw bytes
data: 8-bit bytes
key: 16 8-bit bytes (exactly)
iv: 16 8-bit bytes (exactly)
The output will be raw 8-bit data bytes, exactly as were encrypted. If the encryption input data was ASCII or a unicode encoding the output will also be also.
That is all there is to it. The difficulties are getting the three items (data,key and iv) exactly the same.
Many crypto packages will accept keys and iv that are to short (or missing in the iv case) and pad them to the necessary length somehow. This is non-standard and causes problems. The easy way around this is to supply values that are exactly the correct length. These are data, that is 8-bit bytes, not strings, if you have strings convert then to data. When comparing the data, key and iv do it with hex dumps only. If you do this correxctly the encryption/decryption will just work.
There are a couple of other issues:
The key and iv must be known by both sides (encryption & decryption). The key is generally provided by one side to the other through a separate communications, perhaps even snail-mail. The iv also be shared and need not be secret, in fact it can be sent with the encrypted data.
The key needs to be good and of the correct length. In case it is a password a function is used to make it longer in a non-reversible manner. It should not be really fast. Current best practice is to use the PBKDF2 (Password Based Key Derivation Function) function with an iteration count. Older code tended to use a simple Hash (MD5 or SHA-*) but no longer should be used in new work.
Apple provided APIs for all this in Common Crypto for encryption and key derivation and NSData for Base64 encoding.
For a free PDF of an execelent book Handbook of Applied Cryptography

iOS AES256 decryption

I need to decrypt a string encrypted with AES256.
For example:
This is an encrypted string:
"U2FsdGVkX18egiyzJUY5gHS++2trNSYNSEXpJicKPBE="
using this key:
"70ca7c5b0f58ca290d39613fa3644251"
with the AES256 algorithm
The example string has been encrypted using:
https://code.google.com/p/crypto-js/
There are multiple tools that can be used to decrypt an AES256 encrypted string:
https://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto
https://github.com/RNCryptor/RNCryptor
https://github.com/Gurpartap/AESCrypt-ObjC
I have tried them all but none of them was able to decrypt my string.
I'm sure it's encrypted correctly because I can decrypt it using this online tool:
http://www.appcove.com/tool/aes
Please help me.
Thank you,
George
-------------- EDIT --------------
Can you recommend a symmetric encryption/decryption algorithm for API(js)/iOS?
Something that you used to encrypt strings on the API and decrypt them on your iOS app.
Thank you
To get you started:
This is an encrypted string: "U2FsdGVkX18egiyzJUY5gHS++2trNSYNSEXpJicKPBE="
This is not an encrypted string. It is the Base64 rendering of an array of encrypted bytes. In order to decrypt it you first need to convert it from Base64 back into a byte array.
using this key: "70ca7c5b0f58ca290d39613fa3644251"
This is not a key. It is the hex string representation of the byte array which either is the actual key or can be used to derive the actual key. You need to convert it from a hex string back into a byte array.
with the AES256 algorithm
You need more information here: mode and padding at least.
What mode is being used? AES-ECB, AES-CBC, AES-CTR or some other mode? Look through the description to try and find out. The lack of an IV or a Nonce would probably indicate ECB mode, as Zaph's comment says. ECB mode is insecure, do not use it for any production code.
You also need to know what padding was used. Zaph says PKCS7 padding, which is very common, but the problem source should have told you that. You need to set the decryption method to expect the correct padding.
I'll give you a simple flow to show how AES works:
For the sake of clarity I'll use pseudo-objective-c to make it both understandable for you and fast for me.
// Here comes encryption process:
NSString *key = #"fsd7f897sfd8sfds…";
NSString *secretMessage = #"Confidential text";
AES *aes = [AES sharedAES];
NSString *encryptedMessage = [aes encryptWithKey:key message:secretMessage];
// Now is time for decryption:
Base64 *base64 = [Base64 sharedBase64];
NSString *messageToDecrypt = [base64 decode:encryptedMessage];
NSString *decryptedMesage = [aes decryptWithKey:key message:messageToDecrypt];
// Now you should have the result:
NSLog(decryptedMesage);
Take a look at http://travistidwell.com/jsencrypt/
From the google docs:
For the key, when you pass a string, it's treated as a passphrase and
used to derive an actual key and IV. Or you can pass a WordArray that
represents the actual key. If you pass the actual key, you must also
pass the actual IV.
For CryptoJS.AES.encrypt()
Is a string is passed in as the key another key will be derived and also an iv. This is going to be a compatibility problem because the method of actual key derivation would have to be know as well as the iv derivation and duplicated in iOS.
None of the above is a standard.
The solution is in JavaScript to pass in the key as a WordArray of the correct size (256 bits) and a WordArray iv.
Or per the docs:
"You can define your own formats in order to be compatible with other
crypto implementations. A format is an object with two
methods—stringify and parse—that converts between CipherParams objects
and ciphertext strings.
Then with these the same encryption/decryption can be matched in iOS.
Here is some information I figured out, this is WRT the encrypted data prior to base64 encoding:
The first 8 bytes are "Salted__" Probably used by the Javascript decryption to know the method to use.
The next 8 bytes are random. They are different for each encryption of the same data with same key They may be derived from the key with a random component.
The next bytes are in groups of 16 bytes (blocksize), just enough to contain the data + padding. Padding always adds at least one extra byte.
Because the iv is random the encrypted bytes will be different for each encryption with the same data and key but can be recovered by somehow using the key and leading bytes to re-generate the key and iv. The method is not secret, just unknown to me.
Of course this does not particularly help but does show the problem.

Storing RSA encrypted data as hexadecimal

I am using OpenSSL::PKey::RSA to encrypt/decrypt a string of data using a private key. I am storing the encrypted data in a column in a table as a string. I have gotten this implementation to work no problem using Base64.encode64 and Base64.decode64. However, I do not want to store the encrypted data as base 64, I would like to store it as hexadecimal in a string.
I'm currently using the following to store the encrypted data:
encrypted_data = pk.private_encrypt(plain_data).unpack('H*').first
This results in encrypted_Data equaling a string like that bellow, which easily stores in my database.
d70db8c36d6ccbadd1cca1263ff140df24e0112f636ac9ea92c28f27e443496c
My problem has come in the changing of this hexadecimal string back to the binary string that is needed to decrypt the data. I've tried several different approaches and none seem to work.
What is the best/easiest way to decrypt this hexadecimal string?
The opposite of unpack is pack, which is what you're looking for to get this hex string back to binary. Like so:
[encrypted_data].pack('H*')
Pack is a function on array, not string, so be sure you're passing the same array that unpack('H*') results in or else the output will not be the same.

Raw RSA decryption/signing

I'm implementing RSACryptoToken, that is an interface for RSA cryptographic tokens, according to the documentation.
There are twp methods, called decryptRSA and signRSA - they should be implemented.
In documentation there is an info, that they should perform a raw RSA decryption and raw RSA signing operations.
What means raw RSA operation?
Does it mean, without padding?
Does BlackBerry or Bouncy Castle provides such API?
Basically PKCS#1 v1.5 consists of three parts:
the RSA operations themselves,
the PKCS#1 padding and
an ASN.1 encodign of the hash.
The hash is ASN.1 encoded to include an ASN.1 Object Identifier which uniquely specifies the hash that is used, and the value, like this:
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,
digest OCTET STRING
}
This is directly copied from the PKCS#1 specifications (which are pretty readable and publicly available). Note that the encoding is directly specified as bytes as well in the standards.
Blackberry operations only provide 1) and 2), meaning that you have to supply an ASN.1, DER encoded structure containing the hash yourself. No such a structure is defined for the encryption/decryption, only the padding is removed.
Encryption uses random padding (internally) versus non-random padding for signatures. This allows you to encrypt "YES" twice, while an eavesdropper cannot detect if it is YES or NO. The padding is also required to protect the signature against attacks.
I solved the problem, the operations signRSA and decryptRSA should perform the same pure modulus operation
thanks for help

Resources