Próbuję użyć PBKDF2Withhmacsha512 w PHP z OpenSSL. Ale nie jestem w stanie stworzyć tego samego ciągu, ponieważ Java stworzył zaszyfrowany ciąg. Dane, które próbuję zaszyfrować, jest Atom Insta Pay . Wraz z poniższym kodem Java otrzymuję VNEG6VNDJ3Z4WJ4U3 + Z1G ==, ale w PHP otrzymuję jQuby9xCF + g9yasdnkq7cq ==, który jest całkowicie inny.

// Java code
    import java.util.logging.Logger;
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.PBEKeySpec;
    import javax.crypto.spec.SecretKeySpec;
    
    public class myEncryption {
        static Logger log = Logger.getLogger(myEncryption.class.getName());
        private static int pswdIterations = 65536;
        private static int keySize = 256;
        private static final byte[] ivBytes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    
        public static String encrypt(String plainText, String key) {
            try {
                byte[] saltBytes = key.getBytes("UTF-8");
                SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
                PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, pswdIterations, keySize);
    
                SecretKey secretKey = factory.generateSecret(spec);     
                SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");  
    
                IvParameterSpec localIvParameterSpec = new IvParameterSpec(ivBytes);
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(1, secret, localIvParameterSpec);
    
                byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
    
                return byteToHex(encryptedTextBytes);
    
             }catch (Exception e) {
                log.info("Exception while encrypting data:" + e.toString());
            }
    
            return null;
        }
    
        public static String decrypt(String encryptedText, String key) {
    
            try {
    
                byte[] saltBytes = key.getBytes("UTF-8");
                byte[] encryptedTextBytes = hex2ByteArray(encryptedText);
    
                SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
                PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, pswdIterations, keySize);
    
                SecretKey secretKey = factory.generateSecret(spec);
                SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    
                IvParameterSpec localIvParameterSpec = new IvParameterSpec(ivBytes);
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(2, secret, localIvParameterSpec);
    
                byte[] decryptedTextBytes = (byte[]) null;
                decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
    
                return new String(decryptedTextBytes);
    
            }catch (Exception e) {
                log.info("Exception while decrypting data:" + e.toString());
            }
    
            return null;
        }
    
        private static String byteToHex(byte[] byData) {
            StringBuffer sb = new StringBuffer(byData.length * 2);
    
            for (int i = 0; i < byData.length; ++i) {
                int v = byData[i] & 0xFF;
                if (v < 16)
                    sb.append('0');
                sb.append(Integer.toHexString(v));
            }
    
            return sb.toString().toUpperCase();
        }
    
        private static byte[] hex2ByteArray(String sHexData) {
            byte[] rawData = new byte[sHexData.length() / 2];
            for (int i = 0; i < rawData.length; ++i) {
                int index = i * 2;
                int v = Integer.parseInt(sHexData.substring(index, index + 2), 16);
                rawData[i] = (byte) v;
            }
    
            return rawData;
        }
    }

//PHP code
$method = "AES-256-CBC";
$salt = 'A4476C2062FFA58980DC8F79EB6A799E';
$key = 'A4476C2062FFA58980DC8F79EB6A799E';
$data = 'Demo String';

//Converting Array to bytes
$iv = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
$chars = array_map("chr", $iv);
$IVbytes = join($chars);

$salt1 = mb_convert_encoding($salt, "UTF-8"); //Encoding to UTF-8
$key1 = mb_convert_encoding($key, "UTF-8"); //Encoding to UTF-8

//SecretKeyFactory Instance of PBKDF2WithHmacSHA512 Java Equivalent
$hash = openssl_pbkdf2($key1,$salt1,'256','65536', 'sha512'); 

$encrypted = openssl_encrypt($data, $method, $hash, OPENSSL_RAW_DATA, $IVbytes);

echo base64_encode($encrypted);
1
Sagar Gopale 23 listopad 2020, 12:52

1 odpowiedź

Najlepsza odpowiedź

Rozwiązanie PHP jest znacznie "łatwiejsze" jako Java-Side i może zużywać klucz i sól jako bezpośrednie wejście (bez ich konwersji).

Jak lubisz porównywać Base64-enkoded CipHertsexts Kod próbny zwraca bazę 64 kodowanej CIPHERTEXT, a nie ciąg sześciokątny, ponieważ daje się Java-Prog.

To jest wyjście z równymi wynikami:

expected:  JQubY9xCf+g9yASdNkq7cQ==
encrypted: JQubY9xCf+g9yASdNkq7cQ==

OSTRZEŻENIE BEZPIECZEŃSTWO : Twój kod używa soli statycznej i IV, która sprawia, że szyfrowanie niezabezpieczone (Mam nadzieję, że jest to tylko dla demonstracji).

To jest kod:

<?php
//PHP code
$method = "AES-256-CBC";
$salt = 'A4476C2062FFA58980DC8F79EB6A799E';
$key =  'A4476C2062FFA58980DC8F79EB6A799E';
$data = 'Atom Insta Pay';

//Converting Array to bytes
$iv = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
$chars = array_map("chr", $iv);
$IVbytes = join($chars);

$hash = openssl_pbkdf2($key,$salt,32,65536, 'sha512');
$encrypted = openssl_encrypt($data, $method, $hash, OPENSSL_RAW_DATA, $IVbytes);
echo 'expected:  JQubY9xCf+g9yASdNkq7cQ==' . PHP_EOL;
echo 'encrypted: ' . base64_encode($encrypted);
?>
2
Michael Fehr 23 listopad 2020, 12:39