Note that there are some explanatory texts on larger screens.

plurals
  1. POEncryption error on Android 4.2
    primarykey
    data
    text
    <p>The following code is working on all the versions of android except the latest 4.2</p> <pre><code>import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; /** * Util class to perform encryption/decryption over strings. &lt;br/&gt; */ public final class UtilsEncryption { /** The logging TAG */ private static final String TAG = UtilsEncryption.class.getName(); /** */ private static final String KEY = "some_encryption_key"; /** * Avoid instantiation. &lt;br/&gt; */ private UtilsEncryption() { } /** The HEX characters */ private final static String HEX = "0123456789ABCDEF"; /** * Encrypt a given string. &lt;br/&gt; * * @param the string to encrypt * @return the encrypted string in HEX */ public static String encrypt( String cleartext ) { try { byte[] result = process( Cipher.ENCRYPT_MODE, cleartext.getBytes() ); return toHex( result ); } catch ( Exception e ) { System.out.println( TAG + ":encrypt:" + e.getMessage() ); } return null; } /** * Decrypt a HEX encrypted string. &lt;br/&gt; * * @param the HEX string to decrypt * @return the decrypted string */ public static String decrypt( String encrypted ) { try { byte[] enc = fromHex( encrypted ); byte[] result = process( Cipher.DECRYPT_MODE, enc ); return new String( result ); } catch ( Exception e ) { System.out.println( TAG + ":decrypt:" + e.getMessage() ); } return null; } /** * Get the raw encryption key. &lt;br/&gt; * * @param the seed key * @return the raw key * @throws NoSuchAlgorithmException */ private static byte[] getRawKey() throws NoSuchAlgorithmException { KeyGenerator kgen = KeyGenerator.getInstance( "AES" ); SecureRandom sr = SecureRandom.getInstance( "SHA1PRNG" ); sr.setSeed( KEY.getBytes() ); kgen.init( 128, sr ); SecretKey skey = kgen.generateKey(); return skey.getEncoded(); } /** * Process the given input with the provided mode. &lt;br/&gt; * * @param the cipher mode * @param the value to process * @return the processed value as byte[] * @throws InvalidKeyException * @throws IllegalBlockSizeException * @throws BadPaddingException * @throws NoSuchAlgorithmException * @throws NoSuchPaddingException */ private static byte[] process( int mode, byte[] value ) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { SecretKeySpec skeySpec = new SecretKeySpec( getRawKey(), "AES" ); Cipher cipher = Cipher.getInstance( "AES" ); cipher.init( mode, skeySpec ); byte[] encrypted = cipher.doFinal( value ); return encrypted; } /** * Decode an HEX encoded string into a byte[]. &lt;br/&gt; * * @param the HEX string value * @return the decoded byte[] */ protected static byte[] fromHex( String value ) { int len = value.length() / 2; byte[] result = new byte[len]; for ( int i = 0; i &lt; len; i++ ) { result[i] = Integer.valueOf( value.substring( 2 * i, 2 * i + 2 ), 16 ).byteValue(); } return result; } /** * Encode a byte[] into an HEX string. &lt;br/&gt; * * @param the byte[] value * @return the HEX encoded string */ protected static String toHex( byte[] value ) { if ( value == null ) { return ""; } StringBuffer result = new StringBuffer( 2 * value.length ); for ( int i = 0; i &lt; value.length; i++ ) { byte b = value[i]; result.append( HEX.charAt( ( b &gt;&gt; 4 ) &amp; 0x0f ) ); result.append( HEX.charAt( b &amp; 0x0f ) ); } return result.toString(); } } </code></pre> <p>Here's a small unit test that i've created to reproduce the error</p> <pre><code>import junit.framework.TestCase; public class UtilsEncryptionTest extends TestCase { /** A random string */ private static String ORIGINAL = "some string to test"; /** * The HEX value corresponds to ORIGINAL. &lt;br/&gt; * If you change ORIGINAL, calculate the new value on one of this sites: * &lt;ul&gt; * &lt;li&gt;http://www.string-functions.com/string-hex.aspx&lt;/li&gt; * &lt;li&gt;http://www.yellowpipe.com/yis/tools/encrypter/index.php&lt;/li&gt; * &lt;li&gt;http://www.convertstring.com/EncodeDecode/HexEncode&lt;/li&gt; * &lt;/ul&gt; */ private static String HEX = "736F6D6520737472696E6720746F2074657374"; public void testToHex() { String hexString = UtilsEncryption.toHex( ORIGINAL.getBytes() ); assertNotNull( "The HEX string should not be null", hexString ); assertTrue( "The HEX string should not be empty", hexString.length() &gt; 0 ); assertEquals( "The HEX string was not encoded correctly", HEX, hexString ); } public void testFromHex() { byte[] stringBytes = UtilsEncryption.fromHex( HEX ); assertNotNull( "The HEX string should not be null", stringBytes ); assertTrue( "The HEX string should not be empty", stringBytes.length &gt; 0 ); assertEquals( "The HEX string was not encoded correctly", ORIGINAL, new String( stringBytes ) ); } public void testWholeProcess() { String encrypted = UtilsEncryption.encrypt( ORIGINAL ); assertNotNull( "The encrypted result should not be null", encrypted ); assertTrue( "The encrypted result should not be empty", encrypted.length() &gt; 0 ); String decrypted = UtilsEncryption.decrypt( encrypted ); assertNotNull( "The decrypted result should not be null", decrypted ); assertTrue( "The decrypted result should not be empty", decrypted.length() &gt; 0 ); assertEquals( "Something went wrong", ORIGINAL, decrypted ); } </code></pre> <p>}</p> <p>The line throwing the exception is:</p> <pre><code>byte[] encrypted = cipher.doFinal( value ); </code></pre> <p>The full stack trace is:</p> <pre><code> W/&lt;package&gt;.UtilsEncryption:decrypt(16414): pad block corrupted W/System.err(16414): javax.crypto.BadPaddingException: pad block corrupted W/System.err(16414): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:709) W/System.err(16414): at javax.crypto.Cipher.doFinal(Cipher.java:1111) W/System.err(16414): at &lt;package&gt;.UtilsEncryption.process(UtilsEncryption.java:117) W/System.err(16414): at &lt;package&gt;.UtilsEncryption.decrypt(UtilsEncryption.java:69) W/System.err(16414): at &lt;package&gt;.UtilsEncryptionTest.testWholeProcess(UtilsEncryptionTest.java:74) W/System.err(16414): at java.lang.reflect.Method.invokeNative(Native Method) W/System.err(16414): at java.lang.reflect.Method.invoke(Method.java:511) W/System.err(16414): at junit.framework.TestCase.runTest(TestCase.java:168) W/System.err(16414): at junit.framework.TestCase.runBare(TestCase.java:134) W/System.err(16414): at junit.framework.TestResult$1.protect(TestResult.java:115) W/System.err(16414): at junit.framework.TestResult.runProtected(TestResult.java:133) D/elapsed ( 588): 14808 W/System.err(16414): at junit.framework.TestResult.run(TestResult.java:118) W/System.err(16414): at junit.framework.TestCase.run(TestCase.java:124) W/System.err(16414): at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190) W/System.err(16414): at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175) W/System.err(16414): at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555) W/System.err(16414): at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1661) </code></pre> <p>Does anybody have a clue of what might be happening ? Is anybody aware of a breaking change on android 4.2 in any of the referenced classes? </p> <p>Thanks a lot</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload