I have an online eCommerce websites that uses a third party payment portal. The payment portal was working fine until the third party payment portal have asked everyone to s
Using ECB mode for tamper-proofing input is very stupid.
Having said that, and knowing it's not your fault, because it was not your idea in the first place, and that you just want the code to work, let's ask an independent party to give us a reference point:
echo -n "amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28" | openssl enc -K 38394f5549545550524c334938483347 -aes-128-ecb -base64
Note that openssl takes the key as hexadecimal string, so 89OUITUPRL4I9H3G
should be written as its ASCII sequence 38394f5549545550524c334938483347
The output is:
r7N11xE4HdbJyTByiTDifI1vifvZyNcNfKF+Jo7jEq4rN7c3EiOJxdWOUlCtVXeH
FBTdPSROSmTkUTWfAuOQnHWqe/q/Msd1ykUDIz9eP5L6X6RI0R5UtUXmaakr4klz
1kxEJOjR/WJ5xgd2clBh4iLcYi3caDrCkbD0kRDLQE4=
Let's try to replicate that in Java. To do this, we have to change a few things in your code:
20150101 151515
in the Java code, but 20150101151515
everywhere else. So let's standardize on 20150101151515
Base64.encodeBase64()
does not exist. Java 8 has Base64 encoding built-in, and the code should be Base64.getEncoder().encodeToString(data)
encryptedValue = new String(Base64...)
is unnecessary.encryptedValue
before you can use it.With all that, this compiles in Java 8:
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class encryptData {
public static void main(String[] args) throws Exception {
String data="amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28";
String key="89OUITUPRL3I8H3G";
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] plaintext = data.getBytes();
byte[] ciphertext = cipher.doFinal(plaintext);
String encryptedValue = Base64.getEncoder().encodeToString(ciphertext);
System.out.println(encryptedValue);
}
}
and prints (linebreaks added by me):
r7N11xE4HdbJyTByiTDifI1vifvZyNcNfKF+Jo7jEq4rN7c3EiOJxdWOUlCtVXeH
FBTdPSROSmTkUTWfAuOQnHWqe/q/Msd1ykUDIz9eP5L6X6RI0R5UtUXmaakr4klz
1kxEJOjR/WJ5xgd2clBh4iLcYi3caDrCkbD0kRDLQE4=
Ok so far. What about ruby?
#!/usr/bin/ruby
require 'openssl'
require 'base64'
data = "amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28"
key = "89OUITUPRL4I9H3G"
cipher = OpenSSL::Cipher.new("AES-128-ECB")
cipher.encrypt()
cipher.key = key
crypt = cipher.update(data) + cipher.final
crypt_string = (Base64.encode64(crypt))
puts crypt_string
This prints:
mp8WVhyUHFDqvJKaRXbYKbZT1920TNboRpFLUdPaYsWTkiQ2fhN/tCL6wvtI
B9/Mu08McaKTVIWYeQAfVR5XcUKdeQ+CBcJJRs5krLBjtjiMNlBUq9JpCUaC
0eclfDMaGTE+Z4XSafjPictWzTG/Ye+vkJWC23yxW1zSjBnYBfg=
Why is the ruby code not working? Well i suspect that ruby wants the key in the same way as openssl, because ruby crypto usually uses openssl under the hood. So change the key definition to
key = "38394f5549545550524c334938483347"
key = [key].pack('H*')
This now prints:
r7N11xE4HdbJyTByiTDifI1vifvZyNcNfKF+Jo7jEq4rN7c3EiOJxdWOUlCt
VXeHFBTdPSROSmTkUTWfAuOQnHWqe/q/Msd1ykUDIz9eP5L6X6RI0R5UtUXm
aakr4klz1kxEJOjR/WJ5xgd2clBh4iLcYi3caDrCkbD0kRDLQE4=
which apart from linebreak positions is identical to the output of the other two. Hope you'll be able to get communication with the other side right, and remember:
Using ECB mode for tamper-proofing input is very stupid.