8

I have inherited Android code that uses the following cipher:

ks = new SecretKeySpec(key, "AES");
ciph = Cipher.getInstance("AES");

As only "AES" is given, I don't know what the keysize, modes, and padding are. I've looked over the Bouncy Castle* documentation, but I can't find where the "AES" instance is described. I'd like to use a more explicit instance description (e.g. "AES/ECB/PCKS5Padding"), if I can.

Does anyone know what the keysize, modes, and padding are of this instance?

Thanks!

*I've read that Android uses Bouncy Castle as its default provider, but I haven't found that anywhere official, so I could be making an unhelpful assumption here.

bradreaves
  • 1,463
  • 2
  • 14
  • 16
  • 1
    See http://stackoverflow.com/a/13209169/90322 – Jeff Ferland Dec 07 '12 at 21:23
  • 1
    Once you figure out what the defaults are, correct that code to explicitly request that mode and padding. It was stupid of Sun to ever allow provider-specific defaults. – President James K. Polk Dec 07 '12 at 23:22
  • @GregS From Sun's point of view it's upto whoever wrote the algorithm implementation, this is good as they should know what sensible defaults are and it works even with algorithms that and modes that haven't even been implemented yet. Of course, Sun then went and used poor defaults for those they did implement and then alternate providers used those defaults for those algorithms for compatibility.... And oh, now it's just real bad. – ewanm89 Dec 07 '12 at 23:50
  • @ewanm89: I disagree. The point of cryptography standards is not just security but also interoperability. Having provider-specific defaults hinders interoperability. If they *must* have defaults then they should have been provider-independent, and should simply have been CBC with PKCS5/7 padding for block ciphers. The same holds true for String.getBytes() and the corresponding new String(byte[]) constructor. Those defaults are platform-specific. Big mistake, and will be the cause of the same bugs forever. – President James K. Polk Dec 08 '12 at 01:02
  • @GregS well, at least `String.getBytes()` has a function: communication with other applications and reading/writing system files, although I would rather have had only `String.getBytes(Charset.platformDefault())` to do that. The defaults for `Cipher` are inexcusable in my opinion. – Maarten Bodewes Dec 08 '12 at 03:12
  • By the way, you should *never* use ECB unless you are encrypting symmetric keys, or if you are implementing another mode within a wrapper library. Use at least `"CBC/PKCS5Padding"`, or if available, `"GCM/NoPadding"` – Maarten Bodewes Dec 08 '12 at 14:51
  • @owlstead well, any message <= block size is fairly safe in ECB mode, the less blocks the safer ECB mode is, as the mode isn't yet relevant. Symmetric keys tend to be between 1 (128bit) and 4 (512bit) AES blocks so not very many blocks. Of course, key and/or IV should be unique for each such message otherwise I could process multiple messages the same as a single long message. – ewanm89 Dec 09 '12 at 01:08
  • @ewanm89 Key size and block size are normally not directly related (the initial part of block cipher algorithms is the calculation of sub-keys). IV does not exist for ECB mode. And finally, if you want to use the key multiple times, ECB mode is not safe either. Take a look at my profile before you try and explain this kind of stuff to me :) – Maarten Bodewes Dec 09 '12 at 14:52
  • @owlstead I never claimed they are, but AES specifies a specific block size of 128bit in the specifications (this is one of those defining things that make AES different from Rijndael, However symmetric keys tend to be powers of 2 in length between 128bit and 512bit for current generation of ciphers. This is between 1 and 4 blocks. And yes, I mentioned that key must be unique for each message, and ECB mode with modification for IV is no-longer ECB mode (depending on the modification could be CTR). – ewanm89 Dec 09 '12 at 20:38
  • @owlstead Attacks against ECB work cause same data gives same output and can therefore be correlated. This of course requires a repeated block. In a 1-4 block message of supposedly random data (symmetric key) this is unlikely, though not impossible. Therefore is relatively safe. As long as one keeps cycling those keys. However I'll stick to using other modes myself. – ewanm89 Dec 09 '12 at 20:41
  • 1
    @ewanm89 I don't know what you are trying to accomplish here. I just warned the user against using ECB in a comment because ECB mode encryption in general is not suitable for use. Then I get a whole bunch of comments from you, most of them are questionable and only show your ignorance of cryptography in general. Why don't you stop that? Hint: AES keys of 192 are not powers of two, and 512 bit AES keys don't exist. – Maarten Bodewes Dec 09 '12 at 20:53

2 Answers2

5

Java defaults to "AES/ECB/PKCS5Padding" by default, as specified by the Oracle documentation.

If no mode or padding is specified, provider-specific default values for the mode and padding scheme are used. For example, the SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider:

Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding"); and
Cipher c1 = Cipher.getInstance("DES"); are equivalent statements.

See creating a Cipher object in the Oracle documentation.


I've just checked using a debugger myself. At least for Android 4.0 it seems that Android defaults to the same encryption and padding mode (as expected). The outcome using the default provider of a single (00-valued) byte is a padded plain text with value 000F0F0F0F0F0F0F0F0F0F0F0F0F0F0F in hexadecimals. This is clearly PKCS#5 padding, or more correctly PKCS#7 padding which is the same padding as PKCS#5 for 16-byte block ciphers.


In principle any provider can have a different default from the default "SunJCE" provider. However, that would break applications that assume that the Oracle / OpenJDK default is used.

Instead of leaving your colleague programmers in the dark, it is strongly recommended to specify the entire string including mode & padding and not to rely on defaults for cryptographic algorithms (with the exception of SecureRandom, where specifying the algorithm is usually not recommended).

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
1

From what I know, In java it stands for AES in ECB mode without padding . And I think it's the same on android. I would recomend you running a simple test encrypt something on android and decrypt it using AES/ECB/NoPadding using Java or android. Plus if you don't see any IV in this app it's another, point in this direction.

damiankolasa
  • 1,508
  • 9
  • 8
  • 3
    Just pulled apart an instance in android debugger and can confirm it is ECB mode with no padding by default. – ewanm89 Dec 07 '12 at 22:02
  • 1
    The Sun/Oracle JDK will default to `"PKCS5Padding"` and I would be very very surprised if Android does not keep to that same standard. How did you test? Because the `Cipher` object itself does not return any answer as far as I know. – Maarten Bodewes Dec 08 '12 at 00:21
  • @owlstead: with the Eclipse debugger running Oracle Java 1.6 I could see non-public fields of the Cipher object. The `.spi.core.padding` field was an instance of `com.sun.sun.crypto.provider.PKCS5Padding`, verifying your claim. I would imagine something similar is true on Android. – President James K. Polk Dec 08 '12 at 00:52
  • yes, that's what is used as the padding provider if it is enabled, in bouncy castle running in the android emulator at least there is a second boolean field called padding set to false. – ewanm89 Dec 08 '12 at 13:10
  • @owlstead well in ECB mode it has to have some padding so, I'm not sure exactly what it's doing, but it has that padding field set to false, unfortunately initialising the instances is a far cry from encrypting something, decrypting it again without touching the padding and seeing what it actually did. – ewanm89 Dec 09 '12 at 01:05