2

I am using a MOL API for VOUCHER recharges. Which returns a PIN number in response is successful. That PIN number will be an encrypted text and I need to triple decrypt it!

I contacted the API support, They provided with the code below:

byte[] PinBytes = Base64.decodeBase64(encryptedText.getBytes("utf-8"));
byte[] VectorBytes = Base64.decodeBase64(vectorKey.getBytes("utf-8"));
byte[] SecretKeyBytes = Base64.decodeBase64(secretKey.getBytes("utf-8")); 
TripleDESProvider = CreateTripleDESCryptographicProvider(VectorBytes, SecretKeyBytes)
    DecryptedBytes = TripleDESProvider.Decrypt(PinBytes) 

Here VectorBytes and SecretKeyBytes are security keys provided by them and PinBytes are the response PIN number which is encrypted.

I googled while I was not able to get a correct solution with these three parameters. Any help, please?

I tried this:

try
        {
            String encryptedText = "FN0hbSrVzkqhe+w2rQefAQ==";
            String vectorKey = "7EsBtzAJjMg=";
            //32 bit key
            String secretKey = "08061052989102040806105298910204";
            byte[] PinBytes = Base64.decodeBase64(encryptedText.getBytes("utf-8"));
            byte[] VectorBytes = Base64.decodeBase64(vectorKey.getBytes("utf-8"));
            byte[] SecretKeyBytes = Base64.decodeBase64(secretKey.getBytes("utf-8"));
            final MessageDigest md = MessageDigest.getInstance("md5");
            final byte[] digestOfPassword = md.digest(SecretKeyBytes);
            final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
            for (int j = 0,  k = 16; j < 8;)
            {
                keyBytes[k++] = keyBytes[j++];
            }

            final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
            final IvParameterSpec iv = new IvParameterSpec(VectorBytes);
            final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
            decipher.init(Cipher.DECRYPT_MODE, key, iv);

            //final byte[] encData = new sun.misc.BASE64Decoder().decodeBuffer(message);
            final byte[] plainText = decipher.doFinal(PinBytes);

            System.out.println(plainText.toString());           
        }
        catch (java.security.InvalidAlgorithmParameterException e) { System.out.println("Invalid Algorithm"); }
        catch (javax.crypto.NoSuchPaddingException e) { System.out.println("No Such Padding"); }
        catch (java.security.NoSuchAlgorithmException e) { System.out.println("No Such Algorithm"); }
        catch (java.security.InvalidKeyException e) { System.out.println("Invalid Key"); }
        catch (BadPaddingException e) { System.out.println("Invalid Key");}
        catch (IllegalBlockSizeException e) { System.out.println("Invalid Key");}
        catch (UnsupportedEncodingException e) { System.out.println("Invalid Key");}     
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

Error is Invalid KEY

The document they provide is;

Convert Encrypted Pin into Byte Array from Base64 format

PinBytes = ConvertFromBase64String ("FN0hbSrVzkqhe+w2rQefAQ==")

As Vector Key and Secret Key are provided in Base64 format, thus we need to convert both data into Byte Array as well

VectorBytes = ConvertFromBase64String ("xxxxxxxxx") 
SecretKeyBytes = ConvertFromBase64String ("xxxxxxxxxxxx")

Please create your Triple DES Cryptographic Provider and set your IV byte array and Secret Key byte array into your Provider.

TripleDESProvider = CreateTripleDESCryptographicProvider(VectorBytes, SecretKeyBytes)

Please invokes Triple DES Provider decrypt method.

DecryptedBytes = TripleDESProvider.Decrypt(PinBytes)

Finally convert back decrypted bytes back to string.

ConvertToString(DecryptedBytes)

The result should be 8157151550.

2 Answers2

1

I am not sure if this is the right approach but with AES encryption it works. They provided you the vector, use it to initialize the IVParameterSpec, then create Key object and Cipher instance:

// this is the encripted text
byte[] PinBytes = Base64.decodeBase64(encryptedText.getBytes("utf-8"));

byte[] VectorBytes = Base64.decodeBase64(vectorKey.getBytes("utf-8"));

byte[] SecretKeyBytes = Base64.decodeBase64(secretKey.getBytes("utf-8")); 

// initialize the vector with the one you receive               
IvParameterSpec spec = new IvParameterSpec(VectorBytes);

// create the key. DESede should be correct, but if it doesn't work try also with DES
Key key = new SecretKeySpec(SecretKeyBytes, "DESede");

// Initialize the cipher
Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");

// decrypt the string
c.init(Cipher.DECRYPT_MODE, key, spec);
byte[] decodedDecryptedBytes = c.doFinal(PinBytes);

Base64 object i use is from apache common codec library, but you can use the library you want.

amicoderozer
  • 2,046
  • 6
  • 28
  • 44
  • are you sure the key you provide in your example is correct? As far as I know it should be 24 bytes long. Yours is 32 – amicoderozer Aug 23 '17 at 10:21
  • Yes this is the key provided!! –  Aug 23 '17 at 10:30
  • @KarthikCP The (secret) key used doesn't seem to be base64 encoded. As stated in the previous comment, the key size should be different (168 or 112 bit according to a 3des spec). If you treat is as decimal, converting you will get 14 bytes (112 bit) – gusto2 Aug 23 '17 at 11:48
  • @gusto2 Okk.. So how could i convert it to 112bit –  Aug 23 '17 at 12:01
  • @gusto2 But in their documentation they are saying the secret key is base64 –  Aug 23 '17 at 12:07
  • @KarthikCP but the one you use in your example is not. And it's not 24 bytes long, they should have give you a base64 string (example: `FN0hbSrVzkqhe+w2rQefAQ==`) – amicoderozer Aug 23 '17 at 12:10
  • @gusto2. ALright! Then let me check with them again!! –  Aug 23 '17 at 12:15
  • 1
    @KarthikCP the key treated as base64 encoded, it simply doesn't comply with the 3des standard.. So the simplest option for you is asking for a properly (base64) encoded key. To convert yourself maybe you could use BigInt or BaseNCodec (from apache commons-codec) – gusto2 Aug 23 '17 at 12:17
0

Finally, I Got this answer with same provided secretKey!!

try
        {
            byte[] PinBytes = Base64.decodeBase64(encryptedText);
            byte[] VectorBytes = Base64.decodeBase64(vectorKey);
            byte[] SecretKeyBytes = Base64.decodeBase64(secretKey);
         // initialize the vector with the one you receive               
            IvParameterSpec spec = new IvParameterSpec(VectorBytes);

            // create the key. DESede should be correct, but if it doesn't work try also with DES
            Key key = new SecretKeySpec(SecretKeyBytes, "DESede");

            // Initialize the cipher
            Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");

            // decrypt the string
            c.init(Cipher.DECRYPT_MODE, key, spec);
            byte[] decodedDecryptedBytes = c.doFinal(PinBytes);
            return new String(decodedDecryptedBytes, "UTF-8");      
        }
        catch (java.security.InvalidAlgorithmParameterException e) { System.out.println("Invalid Algorithm"); }
        catch (javax.crypto.NoSuchPaddingException e) { System.out.println("No Such Padding"); }
        catch (java.security.NoSuchAlgorithmException e) { System.out.println("No Such Algorithm"); }
        catch (java.security.InvalidKeyException e) { System.out.println("InvalidKeyException : Invalid Key"); }
        catch (BadPaddingException e) { System.out.println("BadPaddingException : Invalid Key");}
        catch (IllegalBlockSizeException e) { System.out.println("IllegalBlockSizeException : Invalid Key");}
        catch (UnsupportedEncodingException e) { System.out.println("UnsupportedEncodingException : Invalid Key");}     
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;

The Mistake was doing this:

 byte[] SecretKeyBytes = Base64.decodeBase64(secretKey.getBytes("utf-8"));

I don't know why this happens! But by removing that I got the answer!!