Java to ruby AES/ECB/PKCS5Padding encryption

前端 未结 1 1361
一个人的身影
一个人的身影 2021-01-07 12:53

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

相关标签:
1条回答
  • 2021-01-07 13:49

    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:

    1. Your expiryDate is 20150101 151515 in the Java code, but 20150101151515 everywhere else. So let's standardize on 20150101151515
    2. Base64.encodeBase64() does not exist. Java 8 has Base64 encoding built-in, and the code should be Base64.getEncoder().encodeToString(data)
    3. The return type of that is already string so encryptedValue = new String(Base64...) is unnecessary.
    4. Furthermore, you need to declare the type of 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.

    0 讨论(0)
提交回复
热议问题