0

I am creating a project to encrypt and decrypt a file. I have these two algorithms that work fine:

public static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {

    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(clear);
    return encrypted;
}

public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {

    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = cipher.doFinal(encrypted);
    return decrypted;
}

public static byte[] getRaw(String password_) throws Exception {

    byte[] keyStart = password_.getBytes();
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
    sr.setSeed(keyStart);
    kgen.init(128, sr); 
    SecretKey skey = kgen.generateKey();
    byte[] key = skey.getEncoded();  

    return key;
}

Now I need to explain how it works. Does it use a private key? Where is the key storage? Can anyone help me?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
MarcForn
  • 3,321
  • 7
  • 25
  • 39
  • Does it use a private key? In the sense that the key should be private, yes... in the sense of PKI, no. AES doesn't use PKI; like all symmetric encryption methods, it uses a shared secret. As to key storage, it's wherever you choose to store it but your code has nothing even remotely to deal with that problem. These are _extremely_ basic questions; if you're not able to answer them yourself, posting here is not going to get you enough help to pass your exam... you need to spend time in person with your TA/professor or some other real-life-flesh-and-blood tutor. – mah Jan 06 '14 at 11:57
  • Thanks for the answer. I really just have to explain in few steps what does this code do.I have not to go very deep in code. – MarcForn Jan 06 '14 at 12:05

2 Answers2

3

Note: see owlstead's answer for an excellent description of the flaws in your code example

Your encrypt() and decrypt() operations are performing AES encryption and decryption respectively, using Java's JCE libraries. A JCE provider will be selected to perform the actual cryptography - the provider chosen will be the first in the list of providers that offers an implementation of AES. You have defined the algorithm as only "AES", so the mode of operation and padding will be chosen by the provider. If you want to control this, use the form "AES/mode/padding" (see the docs for valid choices)

The getRaw method derives an AES key from a password. The raw bytes of the password provide the seed for a random number generator. The random number generator is then used to generate sufficient key material for a 128-bit AES key. A different password will produce a different seed, which should produce a different stream of random bytes and thus a different key. I suspect this approach is weakened by the lack of entropy present in most people's passwords, leading to a reduced key space and easier attacks.

There is no key storage in your example code. JCE keys are normally persisted using a KeyStore object and the storage mechanism is provider-dependent.

Community
  • 1
  • 1
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • Can you tell me if this is using private key or public key system? – MarcForn Jan 06 '14 at 13:09
  • 1
    This is a [symmetric](http://en.wikipedia.org/wiki/Symmetric-key_algorithm) crypto system. Try to avoid using the word "private" except in the context of an asymmetric crypto system (a.k.a public key crypto system). – Duncan Jones Jan 06 '14 at 13:12
  • 1
    @Duncan Please also see my answer for an insight of the issues with above. – Maarten Bodewes Jan 06 '14 at 15:01
  • @owlstead Hahaha, brilliant. The discord between your polite sounding "an insight of the issues with above" and the first line of your answer "The above piece of code is a bunch of crap" got me chuckling. – Duncan Jones Jan 06 '14 at 15:02
  • I've been fighting that piece of code for some time now. I tried to get it removed from various sites, but up to now to now it's all in vain :( I had more success with the PHP `mcrypt_encrypt` sample code fortunately. – Maarten Bodewes Jan 06 '14 at 18:03
2

The above piece of code is a bunch of crap. Unfortunately it is frequently used as a code snippet for Android related code (Android code uses the same API as Java, so there is no need for an Android specific example, andt unfortunately it specifically fails on Android).

I'll explain the issues:

  1. Using a SecureRandom as Password Based Key Derivation Function (PBKDF) is completely idiotic. The underlying implementation of the SecureRandom implementation may change. Furthermore, it is not specified by the SecureRandom that calling setSeed() as the first method will replace the seed; it may actually add the seed to the current state - and this is what certain newer android versions do.
  2. Cipher.getInstance("AES") actually uses the provider defaults instead of specifying the mode of operation and padding mode for the given cipher. By default the Sun provider will use ECB mode which is not suitable for encrypting most data.
  3. String.getBytes() - which is used for the password - returns the platform default encoding. Different platforms may have different default encodings. This means that different platforms will generate different keys.
  4. Above code does not add a message authentication code (MAC or HMAC). This may lead to an attacker changing random ciphertext blocks, which leads to random plain text blocks. This may lead to loss of confidentiality as well if padding Oracle attacks apply.

It seems to me that you are a beginner in cryptography. Please use a higher level standard such as RNCryptor compatible code, or use a standard such as Cryptographic Message Syntax (CMS).

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Note that my [JNCryptor](https://code.google.com/p/jncryptor/) project is a Java implementation of the RNCryptor format. [AndroJNCryptor](https://github.com/t0mm13b/AndroJNCryptor) is a fork that attempts to be more Android friendly. – Duncan Jones Jan 06 '14 at 15:06