How to get raw key data from passphrase and PBKDF2 iterations - sqlcipher

In SQLCipher it is possible to provide a database key in two ways: either as a passphrase (with an associated number of PBKDF2 rounds) or as a raw key.
I am trying to find a way get the raw key (given as a 64 character hex string) given the passphrase (an arbitrary string) and number of rounds. I assume the solution lies in somehow performing the PBKDF2 key derivation myself, but I'm not too familiar with how this might work, or if it would produce a value that I could just feed as a raw key to PRAGMA KEY. In addition, the PBKDF2 function appears to take a salt, which I do not know. If I have to, I am sure I can dig into the sqlcipher source code to figure this out, but I'm hoping that there might already be a simple way to do this that I'm missing.

The details on SQLCipher key derivation can be found on the design page. The salt is stored in the first 16 bytes of the database file. You would then use the salt along with the passphrase with an appropriate number of PBKDF2-HMAC-SHA1 rounds (64,000 for SQLCipher 3, 4,000 for earlier versions)

Related

Is there a way to decrypt an encoded string without a key in Ruby?

Here's the problem, a string has been passed through three separate encryptions in the following order: Original -> Base64 -> AES-256 -> Blowfish (Keyless) -> Final. Write a method that takes this triple encoded string mystery_string = "OXbVgH7UriGqmRZcqOXUOvJt8Q4JKn5MwD1XP8bg9yHwhssYAKfWE+AMpr25HruA" and fully unencrypts it to its original state.
I looked into different libraries/documentation for aes256 and blowfish but all of them required a key. The only one that did not require a key was Base64 (i.e. Base64.encode64('some string') ). Not really sure where to go from here.
Firstly, the only way to crack AES-256 and Blowfish without the key is by brute force enumeration of every possibly 32-byte combination that could be used as the key. In theory, this means it's not crackable in our lifetime. There may be some vulnerabilities you could exploit as you also have the plain text, but I doubt you would have that in a real-life situation.
Second, and most importantly, just going by that site, encode-decode.comhttps://encode-decode.com/, you don't actually have enough information to decode the string even if you did know the password.
The various modes of operation for the AES256 cipher function requires either a 32-byte (or sometimes a 64-byte) key. The secret that you used (you may have just left it blank) needs to be converted into a 32-byte encryption key. This is done using a hashing algorithm, but we don't know which one is used. Hopefully, the site used a key derivation function, which provides several security benefits. However, key derivation functions require multiple parameters, and we would need to know what parameters to enter along with our secret to get the right encryption key.
Finally, we don't know if the secret is being concatenated with a salt before being hashed. Without knowing if a salt is used and what the salt is, we cannot determine the correct 32-byte key used to encrypt the plain text.
In summary, the answer to your question is: No, there is not a quick way to decrypt that string without knowing the key.
However, encryption is an awesome topic to learn.
I'd encourage you to look over the ruby docs for the OpenSSL library. They're actually quite good (besides the don'ts I mention below).
The PBKDF2 Password-based Encryption function is one of the key derivation functions I was referring to.
When encrypting with AES, you will most likely want to use AES-256-GCM which is authenticated encryption.
A couple of don'ts:
Don't use ciphers at random... understand their strengths and weaknesses
Don't use AES-128-EBC - explination
Another good encryption library is rb-NaCl.

How to Remove Salt from DB?

okay I am trying to make a log in form to my website in C# it has md5 + salt.. the problem is salt. md5 I can make work but salt just won't work. I made a php that gets the user name, user group id's etc. I have removed tons of instances of salt in the db and it either destroyed log in, or just did nothing. I am wondering if there is an easy way to remove salt?
What do you think is the purpose of the salt? If you could easily remove it, what would have been the reason to add it? You should really take a few minutes to read a tutorial about password hashing.
MD5 is not an appropriate choice to hash passwords, because it is ways too fast. One can calculate 8 Giga MD5 values per second with common hardware nowadays, that makes brute-forcing too easy. Instead use a slow key derivation function like BCrypt or PBKDF2.
To answer your question, you need the stored salt to verify the user entered password. If the user enters the password for login, you calculate a hash with the same salt you used to calculate the stored password in the database, then you can compare the hashes.

Blowfish encrypted string becomes gibberish

I need to communicate with an API that requires the request to be encoded in Blowfish and Base64.
In my custom library I start off with:
# encoding: utf-8
require "base64"
require 'crypt/blowfish'
I create an instance:
#blowfish_key = '1234567887654321'
#blowfish = Crypt::Blowfish.new(#blowfish_key)
And further down I create the encrypted string (or 'ticket' as the API calls it)
#string_to_encrypt = "#{#partnerid},#{user.id},#{exam_id},#{return_url},#{time_stamp}"
#enc = #blowfish.encrypt_string(#string_to_encrypt)
In the Rails console I can decrypt with #blowfish.decrypt_string(#enc) without any problems. But the API gives me gibberish:
Invalid ticket:
Decrypted String :)IŠkó}*Ogû…xÃË-ÖÐHé%q‹×ÎmªÇjEê !©†xRðá=Ͳ [À}=»ïN)'sïƒJJ=:›õ)¦$ô1X¢
Also, when I encrypt something simple in the console, like "Hello", and feed the encrypted string to an online Blowfish decoder, like http://webnet77.com/cgi-bin/helpers/blowfish.pl, I get the same gibberish mess back.
It's like the Ruby blowfish encryption is a format that is not used anywhere else.
Note:
In my actual application I send the encrypted string via a form field to the Webservice. The encrypted string is Base64 encoded and prefixed with an 'a'.
#enc = Base64.encode64(#enc)
#enc = 'a' + CGI::escape(#enc)
This is explained in their documentation:
Format of the ticket:
t=’a’ + URL_Encode (
Base64_Encode (
Blowfish_Encrypt ( ‘partnerid,user_id,test_id,URL_Encode(return_URL),ticket_timestamp’, ‘blowfish_key’)
)
)
Note above that the Blowfish_Encrypt function accepts two parameters-
1)the string to encrypt and 2)a hex key. Also note that the ticket has
been prefixed with a lower case ‘a’ (ASCII 97).
Example of what the HTML form will look like:
<form method=”POST” action=”http://www.expertrating.com/partner_site_name/”>
<input type=”hidden” name=”t” value=”adfinoidfhdfnsdfnoihoweirhqwdnd2394yuhealsnkxc234rwef45324fvsdf2” />
<input type=”submit” name=”submit” value=”Proceed to take the Test” />
</form>
I am lost, where do I go wrong?
There's a couple of things:
1) As was said in the comments, if you print the encrypted strings, then this is almost always causing trouble because the encrypted strings are very likely to contain non-ASCII characters that will either be unprintable or in a representation that is not understood by others. The best way to achieve a representation that is widely understood is to encode the result using Base64 or Hex encoding, so the Base64 encoding you apply in your application is fine for that.
2) The Perl app you linked to uses for example hex encoding. As a consequence, it will also only accept encrypted strings in hex encoding. That's why it wouldn't accept any of your inputs at all. You get hex encoding suitable for the application as follows:
hex = encrypted.unpack("H*")[0].upcase
3) But still no luck with the Perl app. One reason is this (taken from Crypt sources):
def encrypt_stream(plainStream, cryptStream)
initVector = generate_initialization_vector(block_size() / 4)
chain = encrypt_block(initVector)
cryptStream.write(chain)
What this means is that Crypt writes the IV as the first block of the encrypted message. This is totally fine, but most modern crypto libraries I know won't prepend the IV but rather assume it is exchanged as out-of-band information between the two communicating parties.
4) But even knowing this, you will still have no luck with the Perl app. The reason is that the Perl app uses ECB mode encryption where the Crypt gem uses CBC mode. CBC mode uses an IV, so even one-block messages won't match except if you are using an all-zero IV. But using an all-zero IV (or any other deterministic IV) is bad practice (and Crypt doesn't do it anyway). Doing so allows distinguishing the first block from random and opens you up to attacks like BEAST. Using ECB is bad practice as well except for totally rare edge cases. So let's forget about that Perl app and concentrate on the things at hand.
5) I'm naturally in favor of using Ruby OpenSSL, but in this case I think I'm not being subjective if I tell you it's better for overall security to use it instead of the Crypt gem. Just telling you so would be lame, so here's two reasons why:
Crypt generates its IVs using a predictable random generator (a combination of srand and rand), but that's not good enough. It has to be a cryptographically secure random generator.
Crypt seems to be no longer maintained and there have been some things going on in the meantime that either were unknown at the time or that were never in the scope of that project. For example, OpenSSL starts to deal with leakage-resilient cryptography to prevent side-channel attacks that target timing, cache misses etc. That has probably never been the intention of Crypt, but such attacks pose a real threat in real life.
6) If my preaching has convinced you to make the change, then I could continue and ask you whether it really has to be Blowfish. The algorithm itself is outstanding, no doubt, but there are better, even more secure options available now, such as AES for example. If it absolutely has to be Blowfish, it's supported by Ruby OpenSSL as well:
cipher = OpenSSL::Cipher.new('bf-cbc')
7) If your production key looks like the one in the example, then there's another weak spot. There's not enough entropy in such strings. What you should do is again use a cryptographically secure random generator to generate your key, which is quite easy in Ruby OpenSSL:
key = cipher.random_key
The nice thing is it will automatically choose an appropriate key length depending on the cipher algorithm to be used.
8) Finally, am I right in assuming that you use that encrypted result as some form of authentication token? As in you append it to the HTML being rendered, wait to receive it back in some POST request and compare the received token with the original in order to authenticate some action? If this is the case, then this would again be bad practice. This time even more so. You are not using authenticated encryption here, which means that your ciphertext is malleable. This implies that an attacker can relatively easily forge the contents of that token without actually knowing your encryption key. This leads to all sorts of attacks, even leading to total compromise involving key recovery.
You must either use authenticated encryption modes (GCM, CCM, EAX...) or use a message authentication code to detect if the ciphertexts had been tampered with. Even better, don't use encryption at all and generate your tickets by using a secure hash function. The key here is to compute the hash of a securely randomized value, otherwise it is again possible to predict the outcome. A timestamp, as used in your example, is not enough. It has to be a cryptographically secure nonce, probably generated by SecureRandom.
But then you still have to consider replay of such tokens, token hijacking, ... you see, it's not that easy.

How to store salt and IV in file cocoa?

So I have implemented salts and IVs, but the decryption is now a bit buggy. Of course, I need both the salt and IV for decryption as well, but the user can't enter that... I need to be able to store both the salt and IV in the encrypted file, then retrieve the salt and IV when the user is decrypting the file. How would I go about doing this? How would I go about storing and retrieving that data?
As Peter said, the initialization vector and the salt for key derivation should be stored together with the encrypted file, in a header or such.
Instead of creating your own ad-hoc file format for encrypted storage, have a look at the OpenPGP message format (as used by both PGP and GnuPG, and maybe other programs). It is specified in RFC 4880. You will likely not have to implement all of it, but grab the portions that you need for your application.
As an added bonus, the user can then use PGP/GPG (with the right options and the password/key) to decrypt the data, if your program should somehow cease to work.
Store them along with the ciphertext. You'll need to come up with a suitable file format in which to do it; a keyed archiver will make it easy.

Encryption puzzle / How to create a PassStub for a Remote Assistance ticket

I am trying to create a ticket for Remote Assistance. Part of that requires creating a PassStub parameter. As of the documentation:
http://msdn.microsoft.com/en-us/library/cc240115(PROT.10).aspx
PassStub: The encrypted novice computer's password string. When the Remote
Assistance Connection String is sent as a file over e-mail, to provide additional security, a
password is used.<16>
In part 16 they detail how to create as PassStub.
In Windows XP and Windows Server 2003, when a password is used, it is encrypted using
PROV_RSA_FULL predefined Cryptographic provider with MD5 hashing and CALG_RC4, the RC4
stream encryption algorithm.
As PassStub looks like this in the file:
PassStub="LK#6Lh*gCmNDpj"
If you want to generate one yourself run msra.exe in Vista or run the Remote Assistance tool in WinXP.
The documentation says this stub is the result of the function CryptEncrypt with the key derived from the password and encrypted with the session id (Those are also in the ticket file).
The problem is that CryptEncrypt produces a binary output way larger than the 15 byte PassStub. Also the PassStub isn't encoding in any way I've seen before.
Some interesting things about the PassStub encoding. After doing statistical analysis the 3rd char is always a one of: !#$&()+-=#^. Only symbols seen everywhere are: *_ . Otherwise the valid characters are 0-9 a-z A-Z. There are a total of 75 valid characters and they are always 15 bytes.
Running msra.exe with the same password always generates a different PassStub, indicating that it is not a direct hash but includes the rasessionid as they say.
Another idea I've had is that it is not the direct result of CryptEncrypt, but a result of the rasessionid in the MD5 hash. In MS-RA (http://msdn.microsoft.com/en-us/library/cc240013(PROT.10).aspx). The "PassStub Novice" is simply hex encoded, and looks to be the right length. The problem is I have no idea how to go from any hash to way the PassStub looks like.
I am curious, have you already:
considered using ISAFEncrypt::EncryptString(bstrEncryptionkey, bstrInputString) as a higher-level alternative to doing all the dirty work directly with CryptEncrypt? (the tlb is in hlpsvc.exe)
looked inside c:\WINDOWS\pchealth\helpctr\Vendors\CN=Microsoft Corporation,L=Redmond,S=Washington,C=US\Remote Assistance\Escalation\Email\rcscreen9.htm (WinXP) to see what is going on when you pick the Save invitation as a file (Advanced) option and provide a password? (feel free to add alert() calls inside OnSave())

Resources