"A pseudorandom generator (PRG) is a deterministic algorithm that takes a short uniformly distributed string, known as the seed, and outputs a longer string that cannot be efficiently distinguished from a uniformly distributed string of that length." [1]
It is my understanding that we can create pseudorandom generators using stream ciphers. For instance, SCAPI, a Secure Multiparty Computation API, uses RC4 in the following example to create an output of a fixed number of bytes (check out.length):
//Create secret key and out byte array
...
//Create prg using the PrgFactory
PseudorandomGenerator prg = PrgFactory.getInstance().getObject("RC4");
SecretKey secretKey = prg.generateKey(256); //256 is the key size in bits.
//set the key
Prg.setKey(secretKey);
//get PRG bytes. The caller is responsible for allocating the out array.
//The result will be put in the out array.
prg.getPRGBytes(out.length, out);
Indeed, pseudorandom generators are particulary useful in some cryptographic protocols (i.e. this protocol) where we need to create a pseudorandom output of bytes, usually of a very large size, fast.
I have actually implemented this protocol using the SCAPI snippet shown above for the PRG part. Yet the authors, instead of using RC4 for their PRG, they use AES128 in CTR mode. Which makes sense since RC4 is known to be broken and since AES can be easily used as stream cipher.
I want to implement a pseudorandom generator using AES in CTR in the same fashion as the snippet above, but I'm unable to do so. My problem is not using AES in CTR, there are countless examples online. My problem is the out.length part. I don't know how to implement a PRG using AES (or any other cipher for that matter) in a way where I get to choose the exact number of output bytes, like the example above. How can I do this?
Before someone mentions that a hash function can do the same job: Indeed, this is basically a hash function but the problem in this particular protocol is that we need very large outputs (i.e. 32MB) where a hash function usually has a fixed output of (192, 256, 512 bits).
Finally, this question is not a duplicate to this one, because the latter is about implementing any kind of PRG in Python where this is one is about implementing an AES_CTR based PRG in Java.
Some useful links:
SCAPI's API
SCAPI's source code on PRGs
In CTR mode you just cut off the bytes you don't need (from the right hand side) of the block encrypt over the last counter. You can create the key stream by performing AES-CTR over the right number (out.length) of zero valued bytes as well.
Related
I following the example from Apache Crypto byte array encryption/decryption from the link below.
https://commons.apache.org/proper/commons-crypto/xref-test/org/apache/commons/crypto/examples/CipherByteArrayExample.html
At line 54 it created a byte[] of size 32, but I don't understand how the author came up with that number. I noticed it is a multiple of 16 which is the key size from line 40. If that is the reason, why not 64, 128, and so on...
It looks like CryptoCipher is a partial mirror of the Cipher instance. Using the Cipher instance requires Apache to implement a provider, and to use Cipher services, the provider needs to be signed. So it makes some sense to have a different class that has about the same API to easily switch between signed and unsigned code.
That out of the way, it seems CryptoCipher lacks a method called Cipher#getOutputSize. That method is used to retrieve the minimum buffer size for an input plaintext. So basically it seems that they've specified a buffer size that is definitely large enough for a ~ 12 byte input string. Then they resize it using Arrays.copyOf(output, updateBytes+finalBytes) later (which will probably result in 16 bytes for ECB or CBC mode).
By the way, that example is such a piece of crap code that I don't have any high hopes for this library. Look at it and understand that this is not the way to perform cryptography. A key and IV are not strings, IV's should be random for each usage and included with the ciphertext. I won't even go into the single utility method getUTF8String that does absolutely nothing special. Where is the try-with-resources? Why is the CryptoCipher missing essential methods?
My qustion is about how should I specify the custom value of AlgorithmParameterSpec in the below program? So that I could use the exact same output value for two different programs, one of which is Server and other is Client. Like I have used the fixed value for Key Generation, I want the same for this AlgorithmParameterSpec.
Client Code Snippet
....
String desKey = "0123456789abcdef"; // value from user
byte[] keyBytes = DatatypeConverter.parseHexBinary(desKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey key = factory.generateSecret(new DESKeySpec(keyBytes));
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
....
Both client and server are on different pcs and are connected on same LAN. However I dont want to send any file from one to another, and neither do I want to write the value of that parameter from client into any file and use it in server. That has already caused too much problems. Is there a way to do this? Or I have to send this generated value from client to server using readUTF and writeUTF?
Original DES aka single-DES has been broken since last century, and should not be used.
In Java, instantiating plain DES like that defaults to DES/ECB/PKCS5Padding (in general Java treats PKCS5 padding as including PKCS7). ECB does not use an IV, and DES has no other parameters, so a java Cipher object for DES/ECB does not need or use any type of parameters object. However, in most applications, ECB mode even with a good cipher (not DES) is insecure and should not be used.
If you change to a more secure mode that does use an IV, like CTR CBC OFB CFB, or better in most applications but only supported in j8+ GCM, then IvParameterSpec is indeed the correct type to use.
However, with modes that use an IV, using a fixed or otherwise duplicated IV is almost always insecure, so you must have a process that provides a unique IV for each encryption and the corresponding decryption(s).
This is often done by choosing a random IV when encrypting and transmitting and/or storing it along with the ciphertext (sometimes simply as the first part of the ciphertext) to be used when decrypting, but other designs that accomplish the same thing are possible. For CTR-based modes including GCM, especially when applied to a stream of traffic between the same parties, using a (scaled) counter provides uniqueness. For CBC the IVs must not only be unique but unpredictable; random is usually easiest for this but it is possible to use an encrypted counter.
Both key and IV (when used) should actually be bits not characters. However it is often convenient to represent them in characters using hex (as you did) or base64. Such character representations can be transmitted and received by a huge variety of methods, of which DataInput/OutputStream or ObjectInput/OutputStream is one among many. There are also many ways to transmit bits (binary) on all networks used in this century (although back in the 1970s and 1980s this was often problematical). Choosing among these may depend on what else your programs are doing and in particular whether they already use things like HTTP, XML, JSON, etc.
I'm trying to figure out a way of implementing Blowfish (or any encryption scheme that will work) in a program I am writing in Java for Android.
I have a sentence, like "I am a dog", which I want to encrypt.
However, before encryption, I encode the sentence with my own 5-bit character representations.
This is my own making, and is like a = "00110" and 'the' = "11001"
So now I have an encoding that is divisible by 5, and looks like
"00011101001101011010"
Is there a way to implement Blowfish to encrypt this binary string, whilst maintaining the length of the bit string.
i.e. the bit string above is 20 bits long. I want the encrypted bit string to also be 20 bits long.
Is this possible with Blowfish? Is it possible at all?
Thanks for any help!
For any block cipher, the cipher text must be at least as big as the block size. That is 64-bits for Blowfish, which means at least a 64-bit output.
If your plaintext is longer than your block size, then you can get the same cipher text size using cipher text stealing: https://en.m.wikipedia.org/wiki/Ciphertext_stealing
Not sure why you are doing the encoding that way, it certainly does not add to security. Also, Blowfish is a dated algorithm: AES is a better choice, but that has block size 128.
Stream ciphers will allow you to get the exact same cipher text size as plaintext size, but I don't know of any good ones implemented in Java. Whatever you do, stay away from rc4: it has real security problems. See the eSTREAM page for possible stream ciphers that should have adequate security. Also, you must never re-use a key for a stream cipher.
EDIT: #CommonsWare pointed out a clever solution from Maarten Bodewes. It looks correct to me, but I don't think you will find an implementation that does this out-of-the-box. Keep in mind also that every ciphertext has to be paired with the IV, which is the same length as the block size (64-bits for blowfish). You should never repeat an IV. My general feeling is that although a clever solution, you're likely going to be better off if you do not have to implement something like this yourself (implementing crypto is dangerous: it is easy to lose security properties by making the smallest mistake).
I have following code -
import org.jasypt.util.text.BasicTextEncryptor;
public static void main(String[] args) {
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
textEncryptor.setPassword("kshitiz");
String cipherText = textEncryptor.encrypt("my_secret");
System.out.println(cipherText);
}
Every time I run it the output is different -
1st run - 7vZzcsVFortOUf4yLyQ9xSEUM2pKSXAs
2nd run - Z3YDxfPpubGAQMpr+5MAKR5P09mAJ7Wd
3rd run - kVGIGcCEXZDFJnV/n0lxyFN5WW7dWMT7
All the outputs are correct as decrypting them gives me my_secret.
How is this so?
Copied from documentation of the method.
The mechanisms applied to perform the encryption operation are described in PKCS #5: Password-Based Cryptography Standard.
This encryptor uses a salt for each encryption operation. The size of the salt depends on the algorithm being used. This salt is used for creating the encryption key and, if generated by a random generator, it is also appended unencrypted at the beginning of the results so that a decryption operation can be performed.
If a random salt generator is used, two encryption results for the same message will always be different (except in the case of random salt coincidence). This may enforce security by difficulting brute force attacks on sets of data at a time and forcing attackers to perform a brute force attack on each separate piece of encrypted data.
Essentially, to comply to the standard, a cryptographic salt which is randomly generated at runtime is used and appended to the output string. This salt prevents brute force attacks using pre-computed rainbow tables.
It is probably using random IVs or random padding. This is actually important for security under some attacks but it will result in different ciphertexts for the same message.
I'm using BouncyCastle to encrypt/decrypt some files using AES and PKCS5 padding in CBC mode :
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
Now two questions:
How can I check that the provided key for decrypting data is correct or not ?
How Can I check encrypted input is untouched (e.g. not changed by user using an HEX editor)?
Thanks
You can use an AEAD mode, like CCM or GCM, in place of CBC. These modes authenticate an encrypted message, so if the wrong key is used, or the cipher text has been altered, you can detect it. You wouldn't be able to distinguish these cases though.
There is support in Java 7's cryptography API for GCM, but the SunJCE provider that ships with Oracle's Java implementation doesn't support it yet. You can get support through third-party providers like BouncyCastle.
You can achieve the same things if you use additional cryptographic services, like a digital signature or message authentication code.
Encryption is not just about the algorithm and the encryption key, it's also a lot about
the system organization.
In general, you can't determine that the key is correct. Any key can be used to decrypt the
data that's supposed to be decrypted, but it's up to some other mechanism to tell you if that
is the "correct" result.
In general, you can't determine if the data to be decrypted is untouched, except through some
external check. It's a property of most encryption systems that changing any of the encrypted
data would change the decrypted output drastically, probably into something you'd interpret
as garbage.
You should add a MAC which first verifies the integrity of the message, and only then you should decrypt it. A common choice of MAC is HMAC with whatever hash function you prefer, such as SHA-2.
Instead of doing this yourself, it's often a good idea to use an authenticated cipher. AES-GCM is a common choice. But you need to be really careful to never reuse an IV in that case.
The JCE ciphers are usually very basic. If you need a full featured protection including integrity and key testing, you need to combine them. And as usual it is better to not device that yourself. So better opt for a more high level format like PKCS7/12 or PGP.
Depending on the Padding used some ciphers will give you a PaddingException when you try to decrypt it with the wrong key. For stronger integrity check I would use a padding consiting of HMAC bytes.
A pretty complete method is included in the JCE, it is the AESWrap algorithm. It requires padded data but will ensure integrity. It is best combined with a length byte as described in RFC 3537. Note, that this is only intended for smaller amounts of secrets (like symmetric keys). The RFC3537 padding is restricted to 255 bytes.
To use this with a password derived key, you can use this:
char[] pass = ... // your password
byte[] codeBytes = ... // up to 255 bytes you want to protect
// generate wrapping key from password
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[16]; rand.nextBytes(salt);
SecretKey kek = f.generateSecret(new PBEKeySpec(pass, salt, 1000, 128));
kek = new SecretKeySpec(password.getEncoded(), "AES"); // convert into AES
// RFC3537 padding (lengthbyte)
byte[] wrappedCodeBytes = new byte[codeBytes + 1 % 8];
System.arraycopy(codeBytes,0,wrappedCodeBytes,1,wrappedCodeBytes.length);
paddedCodeBytes[0]=(byte)codeBytes.length;
byte[] pad = new byte[paddedCodeBytes.length - codeBytes.length -1]; rand.nextBytes(pad);
System.arraycopy(pad,0,paddedCodeBytes,codeBytes.length+1,pad.length);
// AESWrap is WRAP_MODE:needs a SecretKey
SecretKey paddedCodeKey = new SecretKeySpec(paddedCodeBytes, "RAW");
// now wrap the password with AESWrap kek is 128 bit
Cipher c = Cipher.getInstance("AESWrap"); // default IV
c.init(Cipher.WRAP_MODE, kek);
byte[] result = c.warp(paddedCodeKey);
The unwrapping is left for the reader as an exercise :) The example code uses 128bit keysize, since more entropy cant be expected from the PBKDF2 anyway.
Note that this will detect wrong passwords with high probability, and some critics will see this as a weakness of AESWrap.
Take a look at this tutorial on BC encryption, specifically the InitCiphers methods, and in detail at the second code block which specifies the actual type of cipher.
How can I check that the provided key for decrypting data is correct or not?
According to JCE Javadocs, specifically the constructor of Class SecretKeySpec:
This constructor does not check if the given bytes indeed specify a secret key of the specified algorithm. For example, if the algorithm is DES, this constructor does not check if key is 8 bytes long, and also does not check for weak or semi-weak keys. In order for those checks to be performed, an algorithm-specific key specification class (in this case: DESKeySpec) should be used.
Note that Interface KeySpec lists all implementing classes, basically a list of validation options.
How Can I check encrypted input is untouched (e.g. not changed by user using an HEX editor)?
Indeed. That's a good one. 'Input' is pretty generic. Do you mean the actual content to decrypt? Well, if it's munged I believe it will not decrypt properly. Does that make sense?
IFF you are talking about the case of a key with parity bits being altered, as described in item (6) at the Bouncy Castle FAQ, you will have to do an actual parity check on the key. Only the first 56 bytes of the key are used for the encryption ops, and the last 8 bytes are reserved for parity checking. So, essentially, the last part of the 'key' can be changed and the first part is still useful. To detect whether either the parity or the key have been altered, you would run a parity check. I found this little ditty on doing a parity check. And, for more info on how parity is set in these keys, see comments in the JDK7 Crypto Provider source for Class DESKeyGenerator by Jan Luehe (near bottom) which discuss parity setting.
I recently had some interaction with BC, and I hope this info helps.