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.
Related
As the title states, what is the best way to store a base64 string on the HANA Cloud database? I've been using a BLOB column type to store them, but the OData of my database displays it as a SAP ODATA defined "edm.binary" value, and I can't seem to insert more images into the database from my iOS app due to that fact, as I cant find a way to convert a base64 string into binary value
Well, this is not really related to HANA in my opinion, but it is a more general database question. See Storing image in database directly or as base64 data?.
In general, you either store it base64 = string or you store it binary = blob. You should not mix it (both base64 and binary), because it is both reduntant and you have the worst out of both worlds (both difficult to represent it into a plain text representation and also larger size).
To answer your original question, I would strongly NOT recommend you to store a base64 in a blob. As base64 is a simple string, you can use either of the character types, based on how large you expect it to be. See Character String Types (smaller ones, most likely not a fit for your needs) and Large Object types. My recommendation would be to use CLOB (as base64 is ASCII and you don't need full-text search support for it.
I have a string that was salted, hashed with SHA-256, then base64 encoded. Is there a way to decode this string back to its original value?
SHA-256 is a cryptographic (one-way) hash function, so there is no direct way to decode it. The entire purpose of a cryptographic hash function is that you can't undo it.
One thing you can do is a brute-force strategy, where you guess what was hashed, then hash it with the same function and see if it matches. Unless the hashed data is very easy to guess, it could take a long time though.
You may find the question "Difference between hashing a password and encrypting it" interesting.
It should be noted - Sha256 does not encrypt the data/content of your string, it instead generates a fixed size hash, using your input string as a seed.
This being the case - I could feed in the content of an encyclopedia, which would be easilly 100 mb in size of text, but the resulting string would still be 256 bits in size.
Its impossible for you to reverse the hash, to get that 100mb of data back out of the fixed size hash, the best you can do, is try to guess / compute the seed data, hash, and then see if the hash matches the hash your trying to break.
If you could reverse the hash, you would have the greatest form of compression to date.
SHA* is a hash function. It creates a representation (hash) of the original data. This hash is never intended to be used to recreate the original data. Thus it's not encryption. Rather the same hash function can be used at 2 different locations on the same original data to see if the same hash is produced. This method is commonly used for password verification.
You've done the correct thing by using a salt aka SSHA.
SHA and SHA-2 (or SHA-256) by itself without a salt are NOT considered secure anymore! Salting a SHA hash is called Salted SHA or SSHA.
Below is a simple example on how easily it is to de-hash SHA-1. The same can be done for SHA-2 without much effort as well.
Enter a password into this URL:
http://www.xorbin.com/tools/sha1-hash-calculator
Copy paste the hash into this URL:
https://hashes.com/en/decrypt/hash
Here's a page which de-hashes SHA-2. The way this pages works is somebody must have hashed your password before, otherwise it won't find it:
md5hashing dot net/hashing/sha256
Here's a page that claims to have complete SHA-2 tables available for download for a "donation" (I haven't tried it yet):
crackstation dot net/buy-crackstation-wordlist-password-cracking-dictionary.htm
Here's a good article that explains why you have to use SSHA over SHA:
crackstation dot net/hashing-security.htm
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.
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.
I am trying to verify an OAuth signature generated in code against a "known reputable source". All my steps are verified correct except the last, wherein a 'base signature string' is HMAC-SHA1 hashed against a secret key and then base64 encoded.
I have confirmed that my hash value is the same as expected by the algorithm. I then disconfirmed that my base64 encode was the same. Attempting to determine why my encode failed, I wanted to check the encoder I was using.
Here is the (hash) string being base64 encoded:
203ebb13a65cccaae5cb1b9d5af51fe41f534357
Here is the base64 encode that results in my code:
MjAzZWJiMTNhNjVjY2NhYWU1Y2IxYjlkNWFmNTFmZTQxZjUzNDM1Nw==
According to http://www.motobit.com/util/base64-decoder-encoder.asp, that is the correct result:
But, according to http://www.online-convert.com/result/096d7b00138f3726daee5f6ddb107a62 (provided with the secret and base string, not the hash), a different base64 should have been output. Note that the hash output is my correct hash despite the difference in base64:
Finally, the "official" tester (http://hueniverse.com/oauth/guide/authentication/) outputs a third different base64 from the same hash:
I have no idea what I'm doing wrong, and the fact that these tools are outputting different results makes me wonder if there is in fact such a thing as base64 encoding or if they are actually using different algorithms? Perhaps the fact that it's for OAuth would help you help me identify the answer.
Thanks for any leads from the wise.
OK, in this case the first website was making the same "mistake" I was (in my case it was a mistake, the first website may just be making an unstated assumption).
That mistake is whether the hash is interpreted as a string (which gets base64encoded) or as a series of hexadecimal values which get base64encoded. In the former case, the resultant encode is longer than the original string, while in the latter the resultant encode is shorter than the original string. This is not only empirically true but the interwebs show that it is one of the concepts behind the standard in the first place.
The second website, working from (as stated) "hex" data, got the correct answer.
Try to check via https://base64-encode.org
On this website you can convert all types of images to Base64 string.