首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Java中解密来自openssl_encrypt的字符串?

如何在Java中解密来自openssl_encrypt的字符串?
EN

Stack Overflow用户
提问于 2022-01-05 17:20:33
回答 1查看 75关注 0票数 0

我试图在Java中复制下面的PHP类,以解密使用openssl_encrypt加密的字符串。

代码语言:javascript
运行
复制
class Encryption {
    /* Encryption method */
    protected $method = 'aes-128-ctr';
    /* Encryption key */
    private $key;

    /* Property constructor */
    public function __construct($key = FALSE, $method = FALSE){
        /* Check if custom key provided */
        if(!$key) {
            /* Set default encryption if none provided */
            $key = '1234567891234567';
        }
        /* Check for control characters in key */
        if(ctype_print($key)) {
            /* Convert ASCII keys to binary format */
            $this->key = openssl_digest($key, 'SHA256', true);
            
        } else {
            $this->key = $key;
        }
        $this->key = $key;
        /* Check for custom method */
        if($method) {
            /* If it is a valid openssl cipher method, use it */
            if(in_array(strtolower($method), openssl_get_cipher_methods())) {
                $this->method = $method;
            /* If it is not, unrecognised method */
            } else {
                die(__METHOD__ . ": unrecognised cipher method: {$method}");
            }
        }
    }
    /* Get iv bytes length */
    protected function iv_bytes(){
        /* Get length of encryption cipher initialisation vector */
        return openssl_cipher_iv_length($this->method);
    }

    /* Encryption method */
    public function encrypt($data) {
        /* Get initialisation vector binary */
        $iv = openssl_random_pseudo_bytes($this->iv_bytes());
        /* Return IV hex & encryption string */
        return bin2hex($iv) . openssl_encrypt($data, $this->method, $this->key, OPENSSL_ZERO_PADDING, $iv);
    }

    /* Decrypt encrypted string */
    public function decrypt($data){
        /* Get IV string length */
        $iv_strlen = 2  * $this->iv_bytes();
        /* Parse out the encryption string and unpack the IV and encrypted string. $regs is passed by reference in preg_match() */
        if(preg_match("/^(.{" . $iv_strlen . "})(.+)$/", $data, $regs)) {

            list(, $iv, $crypted_string) = $regs;
            print_R($regs);
            /* If there are character representing a hex and the IV string length is divisible by 2 */
            if(ctype_xdigit($iv) && (strlen($iv) % 2 == 0)) {
                /* Decrypt the unpacked encrypted string */
                return openssl_decrypt($crypted_string, $this->method, $this->key, OPENSSL_ZERO_PADDING, hex2bin($iv));
            }
        }

        return FALSE; // failed to decrypt
    }

}

下面是我当前用于Java解密器的沙箱类

代码语言:javascript
运行
复制
public class PHPDecryptor {
    
    private static String removeIVHash(String data) {
        /* IV string length is 128 bit (16 bytes) * 2 */
        int iv_strlen = 2 * 16;
        /* Remove IV hash */
        String encrypted_string = data.substring(iv_strlen);

        return encrypted_string;
    }
    
    
    public static String decrypt(String data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException  {
        
        String encrypted_string = removeIVHash(data);
        
        /* Get bytes for string and key */
        byte[] text_to_decrypt = encrypted_string.getBytes(StandardCharsets.UTF_8);
        String key_string = "1234567891234567";
        byte[] key = key_string.getBytes(StandardCharsets.UTF_8);
        
        /* Get secret key and iv */
        SecretKeySpec secret_key = new SecretKeySpec(key, "AES");
        IvParameterSpec iv = new IvParameterSpec(new byte[16]);
        
        /* Init cipher */
        Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret_key, iv);
        
        /* Decrypt and cast to string */
        byte[] decrypted = cipher.doFinal(text_to_decrypt);
        String result = new String(decrypted, StandardCharsets.UTF_8);

        return result;
    }
    
    public static void main(String[] arg) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        String text_to_decrypt = "203790144a345320d98fb773795d518e/ioQTApeVMV/4g=="; // Encrypted by PHP
        System.out.println(decrypt(text_to_decrypt));
    }
}

但是,我没有得到准确的解密-实际上,Java类的返回结果是完全没有意义的,无效的UTF-8字符。

这里有明显的错误吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-08 08:54:31

你好像没在做任何关于静脉注射的事,只是把它移除。

从您删除的IV中创建一个IVParameterSpec实例。

代码语言:javascript
运行
复制
public static IvParameterSpec getIv(String iv) {
    return new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
}

如果您使用一些分隔符(我喜欢使用":")来分隔IV和其余的密文,那么您可以更好地从字符串中检索iv,这样您就不需要担心已加密的IV长度并像这样检索它:

代码语言:javascript
运行
复制
 private static String decodeIvString(String data) {
   
    String[] parts = data.split(":");
    String iv = decodeHex(parts[0]);
    return iv;
}

显然,您必须在php中的encrypt函数中添加分隔符。然后,您可以将IV传递回getIv()函数。

代码语言:javascript
运行
复制
    /* Encryption method */
public function encrypt($data) {
    /* Get initialisation vector binary */
    $iv = openssl_random_pseudo_bytes($this->iv_bytes());
    /* Return IV hex & encryption string */
    return bin2hex($iv) . ":" . openssl_encrypt($data, $this->method, $this->key, OPENSSL_ZERO_PADDING, $iv);
}

正如上面提到的注释一样,您应该将PKCS5Padding替换为NoPadding

下面是我用来解密的实用代码:

代码语言:javascript
运行
复制
public static byte[] decryptSymmetric(Algorithm algorithm, Key key, IvParameterSpec iv, byte[] data) throws CryptoFailure {
    try {
        Security.addProvider(new BouncyCastleProvider());
        Cipher aes = Cipher.getInstance(algorithm.getMode(), BouncyCastleProvider.PROVIDER_NAME);
        aes.init(Cipher.DECRYPT_MODE, key, iv);
        return aes.doFinal(data);
    } catch (BadPaddingException | IllegalBlockSizeException e) {
        throw new CryptoFailure(e);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
        throw new CryptoError(e);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70597005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档