2

I´m using this code to Encrypt and Decrypt in Java and Android some Strings and in each system I get a different value.

The code I'm using comes from http://www.androidsnippets.com/encryptdecrypt-strings (I won't paste it beacuse it's quite big).

For example in Android for encrypting "aa" I get this: 1C6BD31C57F42ACFD0EDD2DD5B7A92CA

and exactly the same String with the same key as seed in Java I get: 61FAD1203B7AC92AD9345771AA273DA5

Any idea?

Thanks in advance!

Kuu
  • 117
  • 1
  • 12
  • Do you get the same encrypted string if you try again? I would have thought not... There is generally a random component but you can still decrypt it fine. – assylias Mar 15 '12 at 21:44
  • Is there an encoding difference between the desktop and android java versions where 'aa' doesn't represent the same hex? – Thomas Mar 15 '12 at 21:46
  • This snippet is not good; do not use it. Its "key derivation" is not reliable or secure. Use PBKDF2 instead. You can see how [here.](http://stackoverflow.com/a/992413/3474) – erickson Mar 15 '12 at 22:59
  • The problem is that I cannot decrypt, I get an exception about bad padding. (I will check that @erickson) – Kuu Mar 16 '12 at 07:30
  • @erickson I'm trying to implement your answer that you are referring to on Android. However, I'm getting an error when initializing the cipher object at the following line: cipher.init(Cipher.ENCRYPT_MODE, secret); the error says: (InvalidKeyException: Only SecretKey is supported). I think what you have done in Java can not be ported to Android straightforwardly. I implemented your code in a pure Java app and managed to get it working. – Khaled Alanezi Aug 19 '15 at 17:44
  • @KhaledAlanezi What is the stack trace? Googling for the message, I only find code that should not be a problem. The stack trace might show me the name of the class that's actually testing the key so that I can see why it's a problem. – erickson Aug 19 '15 at 17:50
  • @erickson Here is a part from trace: java.security.InvalidKeyException: Only SecretKey is supported; at com.android.org.conscrypt.OpenSSLCipher.engineInitInternal(OpenSSLCipher.java:254); at com.android.org.conscrypt.OpenSSLCipher.engineInit(OpenSSLCipher.java:306); at javax.crypto.Cipher.init(Cipher.java:661); at javax.crypto.Cipher.init(Cipher.java:621) – Khaled Alanezi Aug 19 '15 at 17:59
  • @KhaledAlanezi Okay, I don't see an obvious problem. You are importing `javax.crypto.spec.SecretKeySpec`, and `secret` is an instance of that class, right? You may need to open a new question with an [SSCCE.](http://sscce.org/) – erickson Aug 19 '15 at 18:14

3 Answers3

5

This is just my guess, but I think the reason is your key derivation. I'm not really a Java developer though, so I might not be understanding the code correctly.

This code always calls getRawKey() when you encrypt and decrypt. getRawKey() looks like it takes something they call a seed, or your shared secret, and uses it to compute a new random key to do the actual encryption/decryption.

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(seed);
    kgen.init(128, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();

According to Java docs found here, setSeed() "Reseeds this random object. The given seed supplements, rather than replaces, the existing seed."

My guess is that the initial state of the RNG is different on each system/platform, and thus it's giving you different results. You should fix the key derivation to something more standard and consistent, or use an already established crypto system, like PGP in the Bouncy Castle libraries.

mfanto
  • 14,168
  • 6
  • 51
  • 61
  • I think earlier versions of Android incorrectly did simply use the seed as a starting point of the RNG, this was corrected in later versions, which means that the already broken code is now not running anymore, unfortunately the lame example has lured at least 10s of programmers into the same hole. – Maarten Bodewes Mar 15 '12 at 23:26
  • This answer is correct. In addition, the underlying implementation of the PRNG is not guaranteed to be consistant between platforms (so the PRNG on an Android device is not necessarily going to give the same results with the same seed as one on another platform). If you want this to work, replace the key derivation with something better, like running a good Password-Based Encryption (PBE) algorithm to take the password and form a key (bcrypt and PBKDF2 are two good ones). –  Mar 15 '12 at 23:42
  • Actually, this is not corrected in ICS. Android's SHA1PRNG `SecureRandom` behaves differently than the Java SE one: if you call `setSeed()` before `getBytes()`, the seed will be used to setup the PRNG. On Java SE, it's automatically seeded from `/dev/random`, etc., and `setSeed()` adds to that. So that (broken) code will still work on Android, but if you want some interoperability use PBE. – Nikolay Elenkov Mar 16 '12 at 02:54
  • There's never been any guarantee that PRNGs will work the same across platforms (or even across devices). If you run a Java program using SecureRandom on a Windows host and one on a Unix host, you get different results as the random comes from different places. Same with Android. The lesson is very basic -> don't assume you can ever know from a software-perspective how the PRNG is working and don't rely on this for interoperability...and you shouldn't care at this level of abstraction either. –  Mar 16 '12 at 12:18
1

This example will demonstrate to how to encrypt a sting and decrypt, for that purpose we need a shif key which will shift the one character to another character, for exaple if you have 'b' and using shift key=2 then it will becom 98+2=100 which ='d' and again 100-2=98 which is 'b', so this will perform in this way.

Make your String encrypt here !

final int shift_key = 4; //it is the shift key to move charcter, like if i have 'a' then a=97+4=101 which =e and thus it changes
    String plainText = "piran jhandukhel"; 
    char character; 
     char ch[]=new char[plainText.length()];//for storing encrypt char
   for (int iteration = 0; iteration < plainText.length(); iteration++)
            {
                    character = plainText.charAt(iteration); //get characters
                    character = (char) (character + shift_key); //perform shift
              }     ch[iteration]=character;//assign char to char array
     String encryptstr = String.valueOf(ch);//converting char array to string
     Toast.makeText(this, "Encrypt string is "+ encryptstr Toast.LENGTH_LONG).show();

Make Your String Decrypt here !

   for(int i=0;i<encryptstr.length();i++)
     {
        character=str.charAt(i);
        character = (char) (character -shift_key); //perform shift
            ch[i]=character;
     }
 Stirng decryptstr = String.valueOf(ch);
     Toast.makeText(this, "Decrypted String is "+decryptstr, Toast.LENGTH_LONG).show();
Pir Fahim Shah
  • 10,505
  • 1
  • 82
  • 81
  • 1
    I'll assume this is a joke since the [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) is trivially broken. – kroot Dec 01 '12 at 18:53
  • @kroot yeah it is, but on low level some people still use it,for example if you go to apple iphone market then there is many application based on Caesar cipher. – Pir Fahim Shah Dec 03 '12 at 06:40
0

Looks like it will have different output every time you encrypt it. This is normal.

synic
  • 26,359
  • 20
  • 111
  • 149
  • 1
    That's only true if it's a mode that uses an IV, like CBC or CTR. This appears to be straight ECB, which means identical plaintexts encrypt to the same ciphertext, under the same key. – mfanto Mar 15 '12 at 22:43