使用使用Java

问题描述 投票:0回答:1

我们正在使用以下代码在Java中加密数据,并尝试将逻辑转换为PHP。用一种语言加密的数据不能用另一种语言解密。有什么区别吗? 我的Java代码

public class EncYes { private static final char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; public static void main(String[] args) { try { String encString=null; EncYes enc = new EncYes(); switch(args[0]){ case "e": System.out.println(enc.encrypt(args[1],args[2])); break; case "d": System.out.println(enc.decrypt(args[1],args[2])); break; } } catch (Exception e) { System.out.println(e); } } public String encrypt(String json, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { Cipher cipher = null; EncYes enc = new EncYes(); //byte[] keyBytes = new byte[16]; SecretKeySpec skeySpec = new SecretKeySpec(enc.hexfromString(key), "AES"); byte[] ivSrc = new byte[12]; GCMParameterSpec ivSpec = new GCMParameterSpec(128, ivSrc); cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(1, skeySpec, ivSpec); byte[] encstr = cipher.doFinal(json.getBytes()); return enc.hextoString(encstr); } public String decrypt(String json, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { Cipher cipher = null; EncYes enc = new EncYes(); //byte[] keyBytes = new byte[16]; SecretKeySpec skeySpec = new SecretKeySpec(enc.hexfromString(key), "AES"); byte[] ivSrc = new byte[12]; GCMParameterSpec ivSpec = new GCMParameterSpec(128, ivSrc); cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(2, skeySpec, ivSpec); byte[] encstr = cipher.doFinal(enc.hexfromString(json)); return new String(encstr); } public static byte[] hexfromString(String s) { int i = s.length(); byte[] abyte0 = new byte[(i + 1) / 2]; int j = 0; int k = 0; if (i % 2 == 1) { abyte0[k++] = (byte)HexfromDigit(s.charAt(j++)); } while(j < i) { abyte0[k++] = (byte)(HexfromDigit(s.charAt(j++)) << 4 | HexfromDigit(s.charAt(j++))); } return abyte0; } public static int HexfromDigit(char c) { if (c >= '0' && c <= '9') return c - 48; if (c >= 'A' && c <= 'F') return (c - 65) + 10; if (c >= 'a' && c <= 'f') return (c - 97) + 10; else throw new IllegalArgumentException("invalid hex digit: "); } public static String asHex(byte[] buf) { StringBuffer strbuf = new StringBuffer(buf.length * 2); for(int i = 0; i < buf.length; ++i) { if ((buf[i] & 255) < 16) { strbuf.append("0"); } strbuf.append(Long.toString((long)(buf[i] & 255), 16)); } return strbuf.toString(); } public static String HextoString(byte abyte0[], int i, int j) { char ac[] = new char[j * 2]; int k = 0; for (int l = i; l < i + j; l++) { byte byte0 = abyte0[l]; ac[k++] = hexDigits[byte0 >>> 4 & 0xf]; ac[k++] = hexDigits[byte0 & 0xf]; } return new String(ac); } public static String hextoString(byte[] abyte0) { return HextoString(abyte0, 0, abyte0.length); } public static String generateIv() { UUID uId = UUID.randomUUID(); return uId.toString().replace("-", ""); } }

我的php代码
class EncYes {

    private static $hexDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];

    public static function main($args) {
        try {
            $enc = new EncYes();

            switch ($args[0]) {
                case "e":
                    return $enc->encrypt($args[1], $args[2]) . "\n";
                    break;
                case "d":
                    return $enc->decrypt($args[1], $args[2]) . "\n";
                    break;
            }
        } catch (Exception $e) {
            echo $e->getMessage() . "\n";
        }
    }

    public function encrypt($json, $key) {
        $iv = str_repeat("\0", 12);
        $cipher = "aes-128-gcm";
        $tag = "";

        $encrypted = openssl_encrypt($json, $cipher, $this->hexfromString($key), OPENSSL_RAW_DATA, $iv, $tag,"",12);
        if ($encrypted === false) {
            throw new Exception("Encryption failed");
        }

        return $this->hextoString($encrypted . $tag);
    }

    public function decrypt($json, $key) {
        $iv = str_repeat("\0", 12); // 12-byte IV filled with zeros
        //$iv = base64_decode('AAAAAAAAAAAAAAAA');
        $cipher = "aes-128-gcm";

        $data = $this->hexfromString($json);
        $encrypted = substr($data, 0, -12);
        $tag = substr($data, -12);

       //echo  base64_encode($tag);
        $decrypted = openssl_decrypt($encrypted, $cipher, $this->hexfromString($key), OPENSSL_RAW_DATA, $iv, $tag);
        if ($decrypted === false) {
            throw new Exception("Decryption failed");
        }

        return $decrypted;
    }

    public static function hexfromString($s) {
        $i = strlen($s);
        $abyte0 = array_fill(0, (int)(($i + 1) / 2), 0);
        $j = 0;
        $k = 0;

        if ($i % 2 == 1) {
            $abyte0[$k++] = self::HexfromDigit($s[$j++]);
        }

        while ($j < $i) {
            $abyte0[$k++] = (self::HexfromDigit($s[$j++]) << 4) | self::HexfromDigit($s[$j++]);
        }

        return implode(array_map("chr", $abyte0));
    }

    public static function HexfromDigit($c) {
        if ($c >= '0' && $c <= '9') {
            return ord($c) - ord('0');
        }
        if ($c >= 'A' && $c <= 'F') {
            return (ord($c) - ord('A')) + 10;
        }
        if ($c >= 'a' && $c <= 'f') {
            return (ord($c) - ord('a')) + 10;
        }
        throw new InvalidArgumentException("invalid hex digit: " . $c);
    }

    public static function asHex($buf) {
        $strbuf = "";

        for ($i = 0; $i < strlen($buf); $i++) {
            $byte = ord($buf[$i]);
            if (($byte & 255) < 16) {
                $strbuf .= "0";
            }
            $strbuf .= dechex($byte & 255);
        }

        return $strbuf;
    }

    public static function HextoString2($abyte0, $i, $j) {
        $ac = array_fill(0, $j * 2, '0');
        $k = 0;

        for ($l = $i; $l < $i + $j; $l++) {
            $byte0 = ord($abyte0[$l]);
            $ac[$k++] = self::$hexDigits[$byte0 >> 4 & 0xf];
            $ac[$k++] = self::$hexDigits[$byte0 & 0xf];
        }

        return implode("", $ac);
    }

    public static function hextoString($abyte0) {
        return self::HextoString2($abyte0, 0, strlen($abyte0));
    }

    public static function generateIv() {
        return str_replace("-", "", uuid_create());
    }
}

主要问题是Java代码使用的标签长度为128位(第1个参数,
java php encryption
1个回答
2
投票
),而PHP代码应用于12个字节= 96位(

openssl_encrypt($json, $cipher, $this->hexfromString($key), OPENSSL_RAW_DATA, $iv, $tag,"",12)

中的最后一个参数以及在解密期间分开ciphertext和tag时)
128位保证了最大的安全性,因此应使用此标签长度(除非有较小标签长度的有效理由)。
其他可能的问题,漏洞或效率低下是:

使用PHP代码中指定的算法是

aes-128-gcm
,即仅使用16个字节键,即AES-128,这两个代码才兼容。对于不同的密钥长度或AES变体,必须相应地调整PHP代码中的规范。这在Java侧不需要,因为AES变体是隐式从钥匙长度得出的。

使用零IV,这是基于CTR的模式(如GCM)(至少使用固定键)等基于CTR的模式的关键漏洞,请参见

HERHE
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.