Encryption code segment which I do not understand - java

I am reading about encryption and having a lot of difficulty understanding these 3 Java statements of an encryption program.
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
encrypted = cipher.doFinal(str.getBytes())
Can somebody help?

In simpler terms,
create a new Encrypting Device using the AES algorithm;
make it ready
get the bytes of the string str and encrypt them; return the result into the encrypted object, whatever that is.
what exactly did you not understand?

cipher = Cipher.getInstance("AES");
Get a Cipher object that can encrypt/decrypt using the AES algorithm. Java's cryptography code is a bit weird - instead of directly creating objects, you generally use a getInstance call with a String argument. (Note that "cipher" means "way of encrypting something".)
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
Tell the cipher that you would like to encrypt something (Cipher.ENCRYPT_MODE), and give it the encryption key skeyspec.
encrypted = cipher.doFinal(str.getBytes())
The way ciphers work is that you feed them chunks of byte data using the update method, which causes the cipher to accumulate the encrypted data within itself. For the final block of data, doFinal is used, which tells the cipher that the encryption process is done. A different method is needed because the cipher often has to pad out the data returned to a particular length. doFinal then returns the final bit of encrypted information.
However, if there is a single readily available chunk of data, you can just call doFinal and it will give you all the encrypted bytes at once. But this explains why the method is called doFinal, not say, "process".
So in summary, the code above creates an AES encryption engine, gives it an encryption key, then uses it to encrypt the String str into the byte array encrypted.
Note that cryptography is very tricky business and very easy to get wrong. There's all kinds of things you need warning about that I haven't touched on because my wrists hurt now. So I would heavily recommend you get a copy of Beginning Cryptography with Java - it's where I learned to understand this stuff.

Related

How to decrypt AES with an unknown KEY and IV in Java?

so I'm creating a game for my A level project and I'm now at the stage where I need to be able to encrypt and decrypt text files.
I have figured out encryption using AES-256 in GCM mode however I am using a randomly generated key and IV in order to encrypt the data in the first place. So I was wondering, is there any way in which I can decrypt the text file without knowing the key and iv.
Alternatively, from the encryption method shown below, is there anything I could change so that I will know the key and iv when decrypting the text later on.
NOTE: I'm using the libGDX library to create the game which is why I'm not using the standard method to write to the text file.
Encryption method:
public void encrypt ()
{
byte[] input = w.getSprites().toString().getBytes(); // Data to be encrypted
byte[] encrypted = null; // Encrypted output
Cipher cipher; // Cipher algorithm to be used
try {
// Setup the cipher algorithm to use and select the wanted mode
// AES is the cipher algorithm GCM is the mode
cipher = Cipher.getInstance("AES/GCM/NoPadding");
// Generate a random key for the encryption
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
SecretKey key = keyGenerator.generateKey();
// Generate a random iv for the encryption
SecureRandom randomSecureRandom = new SecureRandom();
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
// Encrypt the data
cipher.init(Cipher.ENCRYPT_MODE, key, randomSecureRandom);
encrypted = new byte[cipher.getOutputSize(input.length)];
int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);
}
catch (NoSuchAlgorithmException |
NoSuchPaddingException |
InvalidKeyException |
ShortBufferException |
IllegalBlockSizeException |
BadPaddingException e) { e.printStackTrace(); }
FileHandle f = Gdx.files.local("bin/default/saves/default/test.txt");
f.writeString(encrypted.toString(), false);
}
Thank you in advance for any answers, they are very much appreciated.
No, you cannot decrypt without knowing the key. What would the point of encryption be if anyone could decrypt the message without even having the key?
If this is intended to hide data from a local user, then pretty much the best you can is obfuscate the data. The machine needs to know the key in order to encrypt and decrypt it and anyone with access to that machine can eventually find that key and use it to decrypt the data for themselves. Even if you don't write anything to disk, local users could look at memory and find the key. Also remember that code can be decompiled.
Basically just keep in mind that anyone with physical access is king and you can't really stop them, just slow them down.
So the best you can do is make it as painful as possible to get the key. String literals in classfiles or property files are easy to read and not at all painful so avoid using those.
See this question for related ways to handle local security.
Also consider using a tool like Proguard to obfuscate (and optimize) your code in general as well.
You could try a brute force attack.
Breaking a symmetric 256-bit key by brute force requires 2128 times more computational power than a 128-bit key. Fifty supercomputers that could check a billion billion (1018) AES keys per second (if such a device could ever be made) would, in theory, require about 3×1051 years to exhaust the 256-bit key space.
Per wikipedia
In reality the 256-bit AES is considered computationally infeasible. The only 'feasible' way to decrypt would be using the same key used to encrypt. Some background on AES.
There is a faster method (still computationally infeasible for 256 bit) called Biclique attack. but I think this is a bit outside the scope of what your asking.
If you decide you need to pass your AES key from the encryption person to the decrytion person you can use RSA encryption which uses asymetric keys. Take a look at my github for a basic RSA implementation.

Encryption using AES 256 and SHA-2

I have a situation where I need to first encrypt a message using a public key and vector, that is already provided. Also as per requirement I need to use SHA-2 as well. For now, I am assuming that I need to hash the encrypted message and then send to the server. I have two questions related to this
1. Is it wise to hash the encrypted message? Also, will sending the encrypted message and hashed value to the server be a good idea?
2. I have done a lot search on internet, but whenever I try to get some example of using AES 256 and SHA-2 together, I actually land up where the difference between the two is explained. Can any help me with some sample code?
Thanks in Advance!!!
Let's break down the stuff first.
Public Key Cryptography
Allows a given pair (Kpriv, Kpub) to be used on a cipher to encrypt and decrypt data.
Any data encrypted with Kpriv can only be decrypted with Kpub and any data encrypted with Kpub can only be decrypted with Kpriv.
A nice and well known example of a public key cipher is RSA.
Asymmetric cryptography requires extremely large keys in order to be secure, such that it's extremely slow to execute! You should never encrypt large amount of data with Asymetric keys cryptography. You can use it in the beginning of a connecition to exchange a symetric key Ks, though.
Symetric Key Cryptography
Allows a Ks to be used on a cipher to encrypt and decrypt data.
An example of a symetric cipher is AES. AES is in fact so versatile you can change lots of parameters, such as, (as you mention) the Blocksize which can be of 128, 192 or 256 bits. AES256 is the AES cipher configured with a blocksize of 256 bits.
The block size is what's used against the provided Ks to perform the actual encryption. Note that your data can be larger than the block size (the algorithm will still work, It'l simply reuse the same Ks). Simply reusing the key every block is known as ECB mode and can reveal patterns if your data is repetitive. An alternative is to use modes like CBC or CTR which rely on also using previous block data and XORing with the next block data, to eliminate such patterns. What mode should you use depends on your data.
Note that, according to your cipher mode, you eventually will need padding. I'm assuming you are already quite familiar with this terms when you asked that question.
Guarantees By Cryptography
Cryptography does guarantee that the encrypted data is confidential but that's just it. It does not give any other guarantees such as whether the data is authentic or whether it has been tampered with or not.
While tampering data will most likely result in unintelligible text even after decryption, in cryptography, there's no such thing as invalid plaintext. As such, you need some mechanism to know if your data is valid or not.
A secure hash algorithm such as SHA can help you know whether your decrypted data is valid or not.
However, for these purposes, you usually shouldn't directly use a Digest algorithm. Try to instead use a MAC. That MAC can use SHA256 algorithm but MAC's and Hashes are not exactly the same.
How To Do It In Practice
If all you want is confidentiality and tampering detection, you would use the cipher and digest (or hash) algorithm as such:
E ks ( SHA(data) || data )
Where E is a symmetric cipher, ks is the shared symmetric key, SHA(data) is the digest of data using a secure hash algorithm, || means concatenation and data is a byte array.
A more safer approach would be:
E ks ( MAC mk(data) || data )
Where mk is the MAC's secret key.
Now just search how to "java symetric cipher" and "java hash byte array" and use the two as I'm describing above.

Java AES En/decryption for a String

I have found an useful AES256 implementation to en/decrypt strings, all work fine except the fact i have to store the initialization vector (IV) for the decoding.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
All there any (secure) alternative methods maybe without CBC, because with CBC i have to store an IV (and in my case i have to share the IV which is really not secure).
I have read an article on this platform concerning it´s possible to encode without CBC but that´s not a good idea because of dictionary attacks.
so, are there any alternatives to encode a string with aes256 (without storing additional data like IV, or salt arrays)?
The idea behind an IV is to use a distinct new random one for every encryption (with the same key).
This is very important to ensure the the security of cipher-modes such as CTR or CBC which would not be secure at all without an IV. Also when using the same key to encrypt the same message twice it will result in two distinct ciphertexts (since the two IVs were distinct).
In short, you should always use an IV.
Usually you just prepend them to the ciphertexts and then extract them before encryption, so you don't have to store them individually.

Converting a image(png) to a string then encrypt the image

I want to encrypt a image and then decrypt it. Is there any good references or tutorials or sample showing how to convert the image into a string then encrypt the string? Or there are other ways in encrypting the image? As I am a newbie to this and also I have went to search but there aren't any easy examples for me to understand and also to follow.
If I'm not wrong, i have to use the FileInputstream, and the ImageIO, but i do not know how does it fully works. Anyone can guide me? thanks
An image is a binary file, so I don't think it makes much sense to convert to a String for the purpose of encryption. This would add quite a bit of overhead and complexity for no additional benefit.
You should probably just encrypt the binary file directly.
See:
How to encrypt/decrypt a file in Java?
If your question is "how do I perform encryption in Java", then have a look at some stuff I've written on Java cryptography, in partcular the section on symmetric key encryption. Essentially, you create some secret key, which can just be a string of random bytes generated with SecureRandom:
byte[] key = new byte[16];
(new SecureRandom()).nextBytes(key);
Then you construct a Cipher object and init it with the key, then pass it the data you need to encrypt:
public byte[] encryptData(byte[] key, byte[] data) {
Cipher c = Cipher.getInstance("AES/CTR/PKCS5PADDING");
byte[] initialCounter = new byte[16];
c.init(Cipher.ENCRYPT_MODE,
new SecretKeySpec(key, "AES"),
new IvParameterSpec(initialCounter));
byte[] encryptedData = c.doFinal(plaintextData);
return encryptedData;
}
There's nothing necessarily very special about encrypting an image-- it's just a bunch of bytes like anything else at the end of the day.
The main problem with cryptography is that there are various subtleties that you need to understand for it to be secure.
This link here may also help you out alot:
Using AES with Java Technology
NB you wont need to convert it to a String more like a byte array-

decipher encfs volume key in java

I'm trying to decipher the encfs volume key in Java. I ran encfs with the standard settings (ie, 192 bit aes encryption). Is there any way to do this?
This is not really a Java question, more an issue of cryptography. A brief investigation into EncFS suggests that the volume key is encrypted by a key derived from a user password. It's probable that this represents the best attack vector: a brute force attack on what is hopefully a weak password. I wouldn't hold out too much hope, however.
For what it's worth, the Java JCE classes in javax.crypto would be your route towards performing symmetric cryptography in Java. The following code snippet shows how you might perform some AES decryption with a plaintext key:
byte[] keyBytes = ...
byte[] volumeKeyFileContents = ...
SecretKeyFactory factory = SecretKeyFactory.getInstance("AES");
SecretKey aesKey = factory.generateSecret(new SecretKeySpec(keyBytes, "AES"));
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // for example
cipher.init(Cipher.DECRYPT_MODE, aesKey);
byte[] plaintext = cipher.doFinal(volumeKeyFileContents);
// (written from memory so may not compile without tweaks)
You would then need to use the plaintext value as a potential candidate for the volume key. Clearly this is a simplified solution and makes many assumptions; you will need to research in more depth the format of these volume key files and the algorithms, modes and padding used during the construction of the encrypted copy.
Good luck.
There is a Java library at https://github.com/mrpdaemon/encfs-java that provides read & experimental write access to the encfs file systems.

Categories

Resources