According to Wikipedia, TripleDES supports 56, 112, and 168-bit key lengths, but the System.Cryptography.TripleDESCryptoServiceProvider.LegalKeySizes says it only accepts 128 and 192-bit key lengths.
The system I'm developing needs to be interoperable (data encrypted by my code needs to be decryptable in PHP, Java, and Objective-C) and I don't who is correct in this case.
So who should I believe? And how can I be sure my encrypted data is portable?
Wikipedia does not say TripleDES supports 56 bit keys. The "keying options" talk about "triple-length" keys and "double-length" keys, the latter "reduces the key size to 112 bits".
The effective key size for the original DES is 56 bit. Such a key is constructed from 64 bit input though, where 8 bits remain unused. The "triple-length" key option thus works with a three times 56 bit (=168) constructed from three times 64 bit (=192 bit) and the "double-length" option works with two times 56 bit keys (=112) constructed from two times 64 bit (=128).
As your TripleDESCryptoServiceProvider needs to derive the actual keys from the 64 bit-based input first, it will only take either 128 bits (double-length) or 192 bits (triple-length) as input and then internally derive the 168 or 112 bit actual keys from that input.
That's standard procedure for TripleDES, so you should have no problems with portability across platforms.
Triple DES will only use 112/168 bits of your 128/192 bit key. .NET asks for more bits for the purpose of alignment (each 56 bit subkey is aligned on a 64 bit boundary).
56 bit DES is broken and I'd expect they've made it harder to use.
I believe some (all?) implementations of DES use only 7 bits per character of the key (ASCII encoding). I'm not sure if the definition of DES allows for 8-bit characters in keys or if it actually ignores the high bit of each byte. I think it's the latter.
However, in .NET key sizes are based on the number of bytes, times 8 bits per byte, even if the underlying algorithm ignores that top bit. That is probably the main discrepancy.
TripleDES runs DES three times with potentially three different 56-bit DES keys. In some implementations the middle run is reversed (encrypting-decrypting-encrypting or "EDE") so that using the same 56-bit DES key for all three duplicates the encryption of simple DES. This was done for compatibility with older systems where both are using hardware-based encryption. I'm not sure if the TripleDESCryptoServiceProvider uses this "EDE" approach or the "EEE" approach (or gives you a choice). Further, the same 56-bit DES key can be used for the first and third run, using a 112-bit key instead of the 168-bit key it could also use.
The certified TripleDESCryptoServiceProvider wouldn't accept 56-bit (64-bit) keys because it's not really 3DES security (you could use DESCryptoServiceProvider instead?). At one time it was determined that the 168-bit EEE (or EDE?) 3DES does not provide any greater security than using a 112-bit (128-bit) key. However, there may be some extreme (generally unavailable) attacks in which the shorter key is theoretically more vulnerable. That may also apply to the EDE vs EEE question.
On your compatibility vs other languages question, .NET's *CryptoServiceProvider classes are just a wrapper API around the underlying Windows CRYPTO library. If the other languages are also using the Windows CRYPTO library it should be compatible. Otherwise, you'd have to find out whether they are using EDE or EEE and make sure all are using the same one (you may or may not have flexibility on that), and obviously use the same key length. They are probably all using the same byte order, but if you find things still don't match up that might be another thing to check. Most likely on Windows they're all using CRYPTO and will probably match up as long as you can set the options the same way for all of them.
Des uses multiples of 64 bit keys, but throws away 8 bits leaving a useful keylength of 64 bits.
Triple des can use double or triple key length.
However because repeating des with the same key decrypts the message running des an even number of times can partially decrypt stuff if the keys share patterns.
For this reason des is always ran an odd number of times.
This is also why you should never choose a key where 64 bit parts repeat.
With triple des 192 bit you thus have a effective key length of 112 bits
Related
I'm trying to decrypt an encrypted h264 I-frame, and I was given a key of length 15, is this even valid?
Should not it be of length 16, so the binary representation would be 128 bits?
If you have a thing you could type on a keyboard, that is not a proper AES key, no matter the length. AES derives its power from the fact that its key is effectively random. Anything you can type on a keyboard in not an effectively random sequence of equivalent length. There are only about 96 characters you can type easily on a Latin-style keyboard. A byte has 256 values. 96^16 is a minuscule fraction of 256^16.
To convert a "password" that a human could type into an effectively random AES key, you need a password-based key derivation function (PBKDF). The most famous and widely available is PBKDF2. There are other excellent PBKDFs including scrypt and Argon2. All of them require a random salt, and all are (in cryptographic terms) very slow to compute.
That said, regarding your framework, it is not possible to guess how they have converted this string into a key. You must consult the documentation or the implementation. There are an unbounded number of ways to convert strings into keys (most of them are terrible, but there are still an unbounded selection to pick from). As Michael Fehr noted they might have done something insecure like padding with zeros. They might also have used a simple hashing function like SHA-256 and either used a 256-bit key or taken the top or bottom 128 bits. Or…almost literally anything else. There is no common practice here. Each encryption system has to document how it is implemented.
(Note that even if you see "AES-128," this is also ambiguous. It can mean "AES with a 128-bit key" or it can mean "AES with a 128-bit block and a key of 128, 192 or 256 bits." While the former meaning is a bit more common, the latter occurs often, for example in Apple documentation, despite being redundant (AES always has a 128-bit block). So even questions like "how long is the key" requires digging into the documentation or the implementation. Cryptography is unfortunately incredibly unstandardized.)
Should not it be of length 16, so the binary representation would be 128 bits?
You are right. For AES only key length of 128, 192 or 256 bit is valid.
I commonly see two possibilities for having a key of different length:
You was given a password, not a key. Then you need as well to ask for a way to generate a key from the password (Hash? PBKDF2? Other?)
Many frameworks will silently accept different key length and then trim or zero-pad the value to fit the required key size. IMHO this is not a proper approach as it gives the developers feeling the key is good and in reality a different (padded or trimmed) value is used.
I know that DES has a key length of 56, but what does the EDE mean and does it effect the key length?
In OpenSSL there is the des-ede-cbc option.
Triple DES, DES-EDE or TDEA (formally speaking) can be used with no less than 3 key sizes.
The most logical form uses 3 separate keys for each of the phases (Encrypt, Decrypt and then Encrypt again, which is the meaning of EDE). It has a key size of 3 times 56 bits or 168 bits, but those are usually encoded with parity bits (the least significant bit of each byte), making 192 bits in total. Due to a meet-in-the-middle attack (already known at the design phase) the security is only around 112 bits, so don't be fooled by the key size alone. Generally we aim for 128 bit or higher security. This is sometimes DES-ABC - as in DES with distinct keys A, B and C.
The two key DES-EDE uses the same keys for the Encrypt phases. The key size is therefore 112 bits, encoded as 128 bits and a security of just around 80 bits, due to various attacks. For some attacks it might even be reduced to just over 63 bits. 80 bits is probably just a bit on the short side nowadays and it isn't recommended by NIST anymore. It is called the ABA key scheme, and technically you'd use BAB for decryption.
Finally single key DES-EDE is mainly used for backwards compatibility. The first encrypt and decrypt (or decrypt and second encrypt) cancel each other out so you're left with just one encrypt. You can guess the key size: 56 bits. Single DES can be easily brute forced, especially when hardware support is used. Single key TDES is never used in software and may not be supported (it just makes sense in hardware, where you don't want to supply a separate implementation of DES in addition to DES-EDE). I guess you'd call the key scheme AAA, but I haven't seen that name around at all.
DES-EDE is much slower than a good implementation of AES, and AES has a security of around 126,8 for a key size of 128 bits (using a very complicated attack). So if you have any chance, choose AES instead. AES has other advantages as well, such as the larger block size and lack of weak keys.
I have pairs of email addresses and hashes, can you tell what's being used to create them?
aaaaaaa#aaaaa.com
BeRs114JrR0sBpueyEmnOWZfnLuigYTA
and
aaaaaaaaaaaaa.bbbbbbbbbbbb#cccccccccccc.com
4KoujQHr3N2wHWBLQBy%2b26t8GgVRTqSEmKduST9BqPYV6wBZF4IfebJS%2fxYVvIvR
and
r.r#a.com
819kwGAcTsMw3DndEVzu%2fA%3d%3d
First, the obvious even if you know nothing about cryptography: the percent signs are URL encoding; decoding that gives
BeRs114JrR0sBpueyEmnOWZfnLuigYTA
4KoujQHr3N2wHWBLQBy+26t8GgVRTqSEmKduST9BqPYV6wBZF4IfebJS/xYVvIvR
819kwGAcTsMw3DndEVzu/A==
And that in turn is base64. The lengths of the encodings wrt the length of the original strings are
plaintext encoding
17 24
43 48
10 16
More samples would give more confidence, but it's fairly clear that the encoding pads the plaintext to a multiple of 8 bytes. That suggest a block cipher (it can't be a hash since a hash would be fixed-size). The de facto standard block algorithm is AES which uses 16-byte blocks; 24 is not a multiple of 16 so that's out. The most common block algorithm with a block size of 8 (which fits the data) is DES; 3DES or blowfish or something even rarer is also a possibility but DES is what I'd put my money on.
Since it's a cipher, there must be a key somewhere. It might be in a configuration file, or hard-coded in the source code. If all you have is the binary, you should be able to locate it with the help of a debugger. With DES, you could find the key by brute force (because a key is only 56 bits and that's doable by renting a bit of CPU time on Amazon) but finding it in the program would be easier.
If you want to reproduce the algorithm then you'll also need to figure out the mode of operation. Here one clue is that the encoding is never more than 7 bytes longer than the plaintext, so there's no room for an initialization vector. If the developers who made that software did a horrible job they might have used ECB. If they made a slightly less horrible job they might have used CBC or (much less likely) some other mode with a constant IV. If they did an again slightly less horrible job then the IV may be derived from some other characteristic of the account. You can refine the analysis by testing some patterns:
If the encoding of abcdefghabcdefgh#example.com (starting with two identical 8-byte blocks) starts with two identical 8-byte blocks, it's ECB.
If the encoding of abcdefgh1#example.com and abcdefgh2#example.com (differing at the 9th character) have identical first blocks, it's CBC (probably) with a constant IV.
Another thing you'll need to figure out is the padding mode. There are a few common ones. That's a bit harder to figure out as a black box except with ECB.
There are some tools online, and also some open source projects. For example:
https://code.google.com/archive/p/hash-identifier/
http://www.insidepro.com/
I feel I have a pretty good understanding of hash functions and the contracts they entail.
SHA1 on Input X will ALWAYS produce the same output. You could use a Python library, a Java library, or pen and paper. It's a function, it is deterministic. My SHA1 does the same as yours and Alice's and Bob's.
As I understand it, AES is also a function. You put in some values, it spits out the ciphertext.
Why, then, could there ever be fears that Truecrypt (for instance) is "broken"? They're not saying AES is broken, they're saying the program that implements it may be. AES is, in theory, solid. So why can't you just run a file through Truecrypt, run it through a "reference AES" function, and verify that the results are the same? I know it absolutely does not work like that, but I don't know why.
What makes AES different from SHA1 in this way? Why might Truecrypt AES spit out a different file than Schneier-Ifier* AES, when they were both given all the same inputs?
In the end, my question boils down to:
My_SHA1(X) == Bobs_SHA1(X) == ...etc
But TrueCrypt_AES(X) != HyperCrypt_AES(X) != VeraCrypt_AES(X) etc. Why is that? Do all those programs wrap AES, but have different ways of determining stuff like an initialization vector or something?
*this would be the name of my file encryption program if I ever wrote one
In the SHA-1 example you give, there is only a single input to the function, and any correct SHA-1 implementation should produce the same output as any other when provided the same input data.
For AES however things are a bit tricker, and since you don't specify what you mean exactly by "AES", this itself seems likely to be the source of the perceived differences between implementations.
Firstly, "AES" isn't a single algorithm, but a family of algorithms that take different key sizes (128, 192 or 256 bits). AES is also a block cipher, it takes a single block of 128 bits/16 bytes of plaintext input, and encrypts this using the key to produce a single 16 byte block of output.
Of course in practice we often want to encrypt more than 16 bytes of data at once, so we must find a way to repeatedly apply the AES algorithm in order to encrypt all the data. Naively we could split it into 16 byte chunks and encrypt each one in turn, but this mode (described as Electronic Codebook or ECB) turns out to be horribly insecure. Instead, various other more secure modes are usually used, and most of these require an Initialization Vector (IV) which helps to ensure that encrypting the same data with the same key doesn't result in the same ciphertext (which would otherwise leak information).
Most of these modes still operate on fixed-sized blocks of data, but again we often want to encrypt data that isn't a multiple of the block size, so we have to use some form of padding, and again there are various different possibilities for how we pad a message to a length that is a multiple of the block size.
So to put all of this together, two different implementations of "AES" should produce the same output if all of the following are identical:
Plaintext input data
Key (and hence key size)
IV
Mode (including any mode-specific inputs)
Padding
Iridium covered many of the causes for a different output between TrueCrypt and other programs using nominally the same (AES) algorithm. If you are just checking actual initialization vectors, these tend to be done using ECB. It is the only good time to use ECB -- to make sure the algorithm itself is implemented correctly. This is because ECB, while insecure, does work without an IV and therefore makes it easier to check "apples to apples" though other stumbling blocks remain as Iridium pointed out.
With a test vector, the key is specified along with the plain text. And test vectors are specified as exact multiples of the block size. Or more specifically, they tend to be exactly 1 block in size for the plain text. This is done to remove padding and mode from the list of possible differences. So if you use standard test vectors between two AES encryption programs, you eliminate the issue with the plain text data differences, key differences, IV, mode, and padding.
But note you can still have differences. AES is just as deterministic as hashing, so you can get the same result every time with AES just as you can with hashing. It's just that there are more variables to control to get the same output result. One item Iridium did not mention but which can be an issue is endianness of the input (key and plain text). I ran into exactly this when checking a reference implementation of Serpent against TrueCrypt. They gave the same output to the text vectors only if I reversed the key and plain text between them.
To elaborate on that, if you have plain text that is all 16 bytes as 0s, and your key is 31 bytes of 0s and one byte of '33' (in the 256 bit version), if the '33' byte was on the left end of the byte string for the reference implementation, you had to feed TrueCrypt 31 '00' bytes and then the '33' byte on the right-hand side to get the same output. So as I mentioned, an endianness issue.
As for TrueCrypt maybe not being secure even if AES still is, that is absolutely true. I don't know the specifics on TrueCrypt's alleged weaknesses, but let me present a couple ways a program can have AES down right and still be insecure.
One way would be if, after the user keys in their password, the program stores it for the session in an insecure manner. If it is not encrypted in memory or if it encrypts your key using its own internal key but fails to protect that key well enough, you can have Windows write it out on the hard drive plain for all to read if it swaps memory to the hard drive. Or as such swaps are less common than they used to be, unless the TrueCrypt authors protect your key during a session, it is also possible for a malicious program to come and "debug" the key right out of the TrueCrypt software. All without AES being broken at all.
Another way it could be broken (theoretically) would be in a way that makes timing attacks possible. As a simple example, imagine a very basic crypto that takes your 32 bit key and splits it into 2 each chunks of 16 bytes. It then looks at the first chunk by byte. It bit-rotates the plain text right a number of bits corresponding to the value of byte 0 of your key. Then it XORs the plain text with the right-hand 16 bytes of your key. Then it bit-rotates again per byte 1 of your key. And so on, 16 shifts and 16 XORs. Well, if a "bad guy" were able to monitor your CPU's power consumption, they could use side channel attacks to time the CPU and / or measure its power consumption on a per-bit-of-the-key basis. The fact is it would take longer (usually, depending on the code that handles the bit-rotate) to bit-rotate 120 bits than it takes to bit-rotate 121 bits. That difference is tiny, but it is there and it has been proven to leak key information. The XOR steps would probably not leak key info, but half of your key would be known to an attacker with ease based on the above attack, even on an implementation of an unbroken algorithm, if the implementation itself is not done right -- a very difficult thing to do.
So I do not know if TrueCrypt is broken in one of these ways or in some other way altogether. But crypto is a lot harder than it looks. If the people on the inside say it is broken, it is very easy for me to believe them.
I'm working on a new licensing scheme for my software, based on OpenSSL public / private key encryption. My past approach, based on this article, was to use a large private key size and encrypt an SHA1 hashed string, which I sent to the customer as a license file (the base64 encoded hash is about a paragraph in length). I know someone could still easily crack my application, but it prevented someone from making a key generator, which I think would hurt more in the long run.
For various reasons I want to move away from license files and simply email a 16 character base32 string the customer can type into the application. Even using small private keys (which I understand are trivial to crack), it's hard to get the encrypted hash this small. Would there be any benefit to using the same strategy to generated an encrypted hash, but simply using the first 16 characters as a license key? If not, is there a better alternative that will create keys in the format I want?
DSA signatures are signficantly shorter than RSA ones. DSA signatures are the twice the size of the Q parameter; if you use the OpenSSL defaults, Q is 160 bits, so your signatures fit into 320 bits.
If you can switch to a base-64 representation (which only requires upper-and-lower case alphanumerics, the digits and two other symbols) then you will need 53 symbols, which you could do with 11 groups of 5. Not quite the 16 that you wanted, but still within the bounds of being user-enterable.
Actually, it occurs to me that you could halve the number of bits required in the license key. DSA signatures are made up of two numbers, R and S, each the size of Q. However, the R values can all be pre-computed by the signer (you) - the only requirement is that you never re-use them. So this means that you could precalculate a whole table of R values - say 1 million of them (taking up 20MB) - and distribute these as part of the application. Now when you create a license key, you pick the next un-used R value, and generate the S value. The license key itself only contains the index of the R value (needing only 20 bits) and the complete S value (160 bits).
And if you're getting close to selling a million copies of the app - a nice problem to have - just create a new version with a new R table.
Did you consider using some existing protection + key generation scheme? I know that EXECryptor (I am not advertising it at all, this is just some info I remember) offers strong protection whcih together with complimentatary product of the same guys, StrongKey (if memory serves) offers short keys and protection against cracking. Armadillo is another product name that comes to my mind, though I don't know what level of protection they offer now. But they also had short keys earlier.
In general, cryptographically strong short keys are based on some aspects of ECC (elliptic curve cryptography). Large part of ECC is patented, and in overall ECC is hard to implement right and so industry solution is a preferred way to go.
Of course, if you don't need strong keys, you can go with just a hash of "secret word" (salt) + user name, and verify them in the application, but this is crackable in minutes.
Why use public key crypto? It gives you the advantage that nobody can reverse-engineer the executable to create a key generator, but key generators are a somewhat secondary risk compared to patching the executable to skip the check, which is generally much easier for an attacker, even with well-obfuscated executables.
Eugene's suggestion of using ECC is a good one - ECC keys are much shorter than RSA or DSA for a given security level.
However, 16 characters in base 32 is still only 5*16=80 bits, which is low enough that brute-forcing for valid keys might be practical, regardless of what algorithm you use.