java - 将 java 转换为 php - 使用 keystore.jks 文件进行 AES 加密
问题描述
我正在尝试将 Java加密和解密方法转换为 PHP。
它是一种带有 keystore.jks 文件的 AES 加密/解密方法。我发现很难做到这一点。
我尝试在 PHP 中使用mcrypt_encrypt方法进行转换。但是找不到使用keystore.jks文件的方法。
如果你们能评论每条重要线路的作用,那就太好了。
function my_aes_encrypt($key, $data) {
if(16 !== strlen($key)) $key = hash('MD5', $key, true);
$padding = 16 - (strlen($data) % 16);
$data .= str_repeat(chr($padding), $padding);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, str_repeat("\0", 16)));
}
function my_aes_decrypt($str, $key){
$str = base64_decode($str);
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
$block = mcrypt_get_block_size('rijndael_128', 'ecb');
$pad = ord($str[($len = strlen($str)) - 1]);
$len = strlen($str);
$pad = ord($str[$len-1]);
return substr($str, 0, strlen($str) - $pad);
}
public class MainClass {
public static void main(String[] args) {
try {
String ALIAS = "alias";
String KEYSTORE_PASSWORD = "key_pass";
String KEY_PASSWORD = "k_pass";
KeyStore keyStore = KeyStore.getInstance("JCEKS");
FileInputStream stream = new FileInputStream("path/to/keyFile.jks");
keyStore.load(stream, KEYSTORE_PASSWORD.toCharArray());
Key key = keyStore.getKey(ALIAS, KEY_PASSWORD.toCharArray());
String data = "text to encrypt";
//Encrypt Data
String encryptedData = encryptWithAESKey(data, key.getEncoded());
System.out.println("Encrypted Data : " + encryptedData);
//Decrypt Data
System.out.println("Decrypted Data : " +decryptWithAESKey(encryptedData, key.getEncoded()));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String encryptWithAESKey(String data, byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
SecretKey secKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secKey);
byte[] newData = cipher.doFinal(data.getBytes());
return Base64.encodeBase64String(newData);
}
public static String decryptWithAESKey(String inputData, byte[] key) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("AES");
SecretKey secKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secKey);
byte[] newData = cipher.doFinal(Base64.decodeBase64(inputData.getBytes()));
return new String(newData);
}
}
解决方案
php代码什么都不做——这只是加密和解密程序;
java代码用encryptWithAESKey()加密数据,然后用decryptWithAESKey()解密。密钥是从文件“path/to/keyFile.jks”加载的(假路径,你可以改变它)你有这个密钥文件吗?看看我的编码器类:
<?php
class AES {
const M_CBC = 'cbc';
const M_CFB = 'cfb';
const M_ECB = 'ecb';
const M_NOFB = 'nofb';
const M_OFB = 'ofb';
const M_STREAM = 'stream';
protected $key;
protected $cipher;
protected $data;
protected $mode;
protected $IV;
/**
*
* @param type $data
* @param type $key
* @param type $blockSize
* @param type $mode
*/
function __construct($data = null, $key = null, $blockSize = null, $mode = null) {
$this->setData($data);
$this->setKey($key);
$this->setBlockSize($blockSize);
$this->setMode($mode);
$this->setIV("");
}
/**
*
* @param type $data
*/
public function setData($data) {
$this->data = $data;
}
/**
*
* @param type $key
*/
public function setKey($key) {
$this->key = $key;
}
/**
*
* @param type $blockSize
*/
public function setBlockSize($blockSize) {
switch ($blockSize) {
case 128:
$this->cipher = MCRYPT_RIJNDAEL_128;
break;
case 192:
$this->cipher = MCRYPT_RIJNDAEL_192;
break;
case 256:
$this->cipher = MCRYPT_RIJNDAEL_256;
break;
}
}
/**
*
* @param type $mode
*/
public function setMode($mode) {
switch ($mode) {
case AES::M_CBC:
$this->mode = MCRYPT_MODE_CBC;
break;
case AES::M_CFB:
$this->mode = MCRYPT_MODE_CFB;
break;
case AES::M_ECB:
$this->mode = MCRYPT_MODE_ECB;
break;
case AES::M_NOFB:
$this->mode = MCRYPT_MODE_NOFB;
break;
case AES::M_OFB:
$this->mode = MCRYPT_MODE_OFB;
break;
case AES::M_STREAM:
$this->mode = MCRYPT_MODE_STREAM;
break;
default:
$this->mode = MCRYPT_MODE_ECB;
break;
}
}
private function pkcs5_pad ($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
/**
*
* @return boolean
*/
public function validateParams() {
if ($this->data != null && $this->key != null && $this->cipher != null) {
if(strlen($this->key) > 16) $this->setKey(substr($this->key, 0, 16));
if(strlen($this->key) < 16){ $n = 1 + intval(16 / strlen($this->key)); $this->setKey(substr(str_repeat($this->key, $n), 0, 16));}
$size = mcrypt_get_block_size($this->cipher, $this->mode);
$this->data = $this->pkcs5_pad($this->data, $size);
return true;
} else {
return FALSE;
}
}
public function setIV($IV) {
$this->IV = $IV;
}
protected function getIV() {
if ($this->IV == "") {
$this->IV = mcrypt_create_iv(mcrypt_get_iv_size($this->cipher, $this->mode), MCRYPT_RAND);
}
return $this->IV;
}
/**
* @return type
* @throws Exception
*/
public function encrypt() {
if ($this->validateParams()) {
return trim(base64_encode(
mcrypt_encrypt(
$this->cipher, $this->key, $this->data, $this->mode, $this->getIV())));
} else {
throw new Exception('Invlid params!');
}
}
/**
*
* @return type
* @throws Exception
*/
public function decrypt() {
if ($this->validateParams()) {
return trim(mcrypt_decrypt(
$this->cipher, $this->key, base64_decode($this->data), $this->mode, $this->getIV()));
} else {
throw new Exception('Invlid params!');
}
}
}
和用法示例:
$crypt = new AES('{"username":"Tiger","amount":20,"source":1,"ttime":1517405737}', "49c50ba2129b7730", 128);
$encdata = $crypt->encrypt();
$crypt = new AES($encdata, "49c50ba2129b7730", 128);
$data = $crypt->decrypt();
推荐阅读
- iis - .net 核心服务从远程桌面会话访问串行端口
- python - 霍夫圆检测 AttributeError:“NoneType”对象没有属性“rint”
- ios - 无法将“URL”类型的值转换为预期的参数类型“Bool”
- apache-spark - 在 spark 2.4.X 中获取 kafka 标头
- javascript - 即使在 DOM 被渲染之后,HTML 集合长度也是 0
- java - Android 尝试在 OTA 应用更新后引用广播接收器的旧包名称
- python - 使用 Plotly 从列表中绘制点图
- c# - 如何等待对象结束旋转然后播放动画?
- java - 可运行的 JAR 工作但没有完成它的工作
- java - 转义特殊字符,如 Java 中的 +