Process to encrypt a 128 bit string [closed] - ios

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

Related

Delphi - Amazon MWS API - How do derive the Base64 HMAC from the SHA 256 HMAC?

Using:
Delphi 10.2.3 Tokyo
IPWorks SSL, IPWorks Encrypt
I'm writing a Delphi app to get order list from Amazon MWS API.
I've followed their instructions here:
https://docs.aws.amazon.com/general/latest/gr/signature-version-2.html
and here:
https://docs.developer.amazonservices.com/en_US/dev_guide/DG_SigningQueryRequest.html
But I am stuck at the signature generation process, specifically generating the Base64 HMAC.
I'm using IPWorks SSL components (Hash component) and am able to generate the SHA 256 signature based on the inputs. Upto this step everything is okay.
Its the next step that I am unable / unsure how to perform.
I'm using the Amazon scratchpad to generate the request and am seeing the request details, and the signatures generated: both SHA 256 and then the Base 64.
My Delphi code does not produce a Base 64 string like the one generated in the scratchpad. Please see the attached screen capture (sensitive information has been redacted).
This is my Delphi code to convert the SHA 256 string to Base 64:
procedure TAppMain.Button1Click(Sender: TObject);
var
s: String;
b: TBytes;
begin
s := '9660152e55a7178db9a9521cd80b7f4872f4be2290d1dd0f32205708f2e06589';
s := TNetEncoding.Base64.Encode(s);
// Above line produces:
// OTY2MDE1MmU1NWE3MTc4ZGI5YTk1MjFjZDgwYjdmNDg3MmY0YmUyMjkwZDFkZDBmMzIyMDU3MDhmMmUwNjU4OQ==
// which is not equal to:
// lmAVLlWnF425qVIc2At/SHL0viKQ0d0PMiBXCPLgZYk=
end;
There is a StackOverflow question that is facing the same issue, and I have tried the suggestion in the answer to that question but I am still unable to derive the same result as the Amazon Scratchpad. Specifically:
The SHA256 Scratchpad shows is not the value you convert with base64.
You have to convert the Hex-Value of the SHA256.
I've spent 2 whole days trying so many things to get the correct result, have read so many articles from Google search results, but I am still unable to find the answer.
Please see my other related question that shows the complete Delphi code, and the complete description of the problem that I am facing:
Delphi - Calculating Amazon MWS signature
Can someone please help me!?
That's because you don't understand the whole point of Base64 at all, including how to write it correctly. Its main purpose is to carry 8bit data (i.e. whole bytes) safely thru 7bit (i.e. ASCII):
When encoding 6bits are taken and displayed as one letter.
When decoding one letter is taken and 6bit of original data are restored.
Which is also the reason why encoding inflates the size by 1/3. When sending attachments in emails the former are stored in Base64, because emails are only 7bit safe. Which is the reason why sending a 4 MiB big picture ends up producing an email of at least 5.2 MiB.
No, it makes no sense to Base64 encode something that is already ASCII and as such 7bit safe. Everybody should be alarmed when someone wants him to Base64 encode the text 9660152e55a7178db9a9521cd80b7f4872f4be2290d1dd0f32205708f2e06589.
You want to encode bytes, not text. What you see is the hex representation of those bytes. You actually want this:
var
input: Array of Byte;
output: String;
begin
SetLength( input, 32 ); // Represented in hexadecimal it would be a text of 64 characters
input[0]:= $96;
input[1]:= $60;
input[2]:= $15;
...
output:= TNetEncoding.Base64.Encode( input );
if output<> 'lmAVLlWnF425qVIc2At/SHL0viKQ0d0PMiBXCPLgZYk=' then Halt(); // Expected output
It's even more obvious when just trying to decode what you expect and just looking straight at it: once as if it's text, and once which byte values every character actually has (because you'll see it's not text at all). Text is not bytes, and vice versa. That's why Base64 exists. Not just for fun.

Multiple encryption append to a file

I have a log of a programs state. This log can be manualy or time interval saved on a file for persistant storage. Before saving it to the file it is encrypted with RNCryptor.
My current appending(saving) to file flow:
Read file
Decript information from the read string
Concat decrypted string with the new string
Encrypt the concatenated string
Write it to file
What I imagine:
Encode new string
Append to file
When I read this I will have to build a string from all the encoded strings. But I don't know how to decrypt the file with multiple encrypted blocks in it. How to differentiate where one ends and another begins.
Also is this the best performance choice. The text in the file at maximum could get to 100MB(Possibly it will never get this big).
Is using Core Data viable? Each append as different record or something. And core data could be encrypted so no need for RNCryptor.
Would appreciate code in Objective-C if any.
There are many things you can do:
Easiest would be to encode the ciphertexts to text (e.g. with Base64) and write each encoded ciphertext to a new line. You need encoding for that, because the ciphertext itself might contain bytes that can be interpreted as newline control characters, but that won't happen with a text encoding. The problem with this is that it blows up the logs unnecessarily (e.g. by 33% if Base64 is used)
You can prepend each unencoded ciphertext with its length (e.g. big-endian int32 encoding) and write both as-is to a file in binary mode. If you begin reading the file from the beginning, then you can distinguish each ciphertext, because you know how long the following ciphertext is and when the next encoded length starts. The blowup is only as big as the encoding of the ciphertext length for each ciphertext.
Use a binary delimiter such as 0x0101 between ciphertexts, but such a delimiter might still appear in the ciphertexts, so you need to escape it if you find it somewhere in the ciphertext. This is a little tricky to get right.
If the amount of logs is small (few MB), then you can find a library to append to a ZIP file.
You can use the array to store the information and then read and write that array to file. find Example here.
Steps :
Read Array from the file.
Add the New Encrypted string to array.
Write array to file.

Encrypting file names [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need an encryption method that will encrypt (not encode) a file name so that the resulting encrypted string can be stored in a SQLite table.
The encryption method must not insert #0 characters into the resulting TString (non ANSI).
Example:
Before: hello_world.txt
After: y381a82jzseoi1
The length of the two strings needs to be the same, or at least not more than 10-15% longer in length.
Any suggestions?
I would do it like this:
Convert from text to binary using TEncoding.GetBytes. You'll need to decide on an encoding. To support Unicode UTF-8 or UTF-16 would be the most likely choices. Often UTF-8 is the most efficient in terms of space.
Encrypt using your chosen encryption algorithm. This converts the binary data returned by TEncoding.GetBytes into encrypted binary data.
Save the encrypted binary data to the database as a blob.
Note that I have avoided converting the encrypted binary data back to text. This deals with your desire to avoid null-terminators by simply side-stepping the issue. The key point for you to recognise is that encryption operates on binary data rather than text. It is an exceptionally common misconception that encryption algorithms operate on text.
If, for some reason that I do not anticipate, you simply must store the data as text, then you should encode it from binary to text. You could implement base255 encoding to avoid having null terminators, and keep the size down.

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.

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