【问题标题】:How to replicate Java encryption in PHP?如何在 PHP 中复制 Java 加密?
【发布时间】:2016-07-03 14:35:19
【问题描述】:

我正在努力完成的一些背景。

第 1 部分。

PHP 服务器与基于 Java 的设备通信。 PHP 使用 OpenSSL 生成公钥/私钥对,然后将公钥发送到设备,该设备反过来返回加密的macKey(使用公钥生成),以 base64 编码。 PHP 现在需要使用私钥对 macKey 进行 base64 解码和解密。

下面的Java代码sn-p在PHP中的等价物是什么?

String base64EncodedMacKey = "LkvTT9LFj5lcxRRB8KrwwN906fSIDDcJvQK3E7a5PbR+Ox9WnslOs32jSCC9FkE8ouvr2MfWwtppuZmoPjaxwg3yAQI4UN3T1loISuF2VwKWfJ45fywbK9bNnD5Cw7336mjoGctv77Tg3JXPrsRwgMGIlBsNwdt1B0wgT4MMMAjl32TnBI3iwQ94VTMHffrK+QToddTahRHHoVsr3FVrETdiqKXdkiX1jES53im5lrXYIsY89UFkGzPo+3u4ijKIQWSLvYnA5wXI128gFHKxKYS82MbJDUn9i1RVFsGaP6T3nQRSX5SZNpSe5yGFWwMgYOx0KXMgET82FeaL2hfWuw==";
byte[] base64DecodedMacKey = DatatypeConverter.parseBase64Binary(base64EncodedMacKey);

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, keypair.getPrivate());

byte[] macKey = cipher.doFinal(base64DecodedMacKey);

这是我在 PHP 中尝试的,但是在解密 macKey 时我对使用字节数组与字符串感到困惑

$macKey = 'LkvTT9LFj5lcxRRB8KrwwN906fSIDDcJvQK3E7a5PbR+Ox9WnslOs32jSCC9FkE8ouvr2MfWwtppuZmoPjaxwg3yAQI4UN3T1loISuF2VwKWfJ45fywbK9bNnD5Cw7336mjoGctv77Tg3JXPrsRwgMGIlBsNwdt1B0wgT4MMMAjl32TnBI3iwQ94VTMHffrK+QToddTahRHHoVsr3FVrETdiqKXdkiX1jES53im5lrXYIsY89UFkGzPo+3u4ijKIQWSLvYnA5wXI128gFHKxKYS82MbJDUn9i1RVFsGaP6T3nQRSX5SZNpSe5yGFWwMgYOx0KXMgET82FeaL2hfWuw==';
$base64DecodedMacKey = base64_decode($macKey);
openssl_private_decrypt($base64DecodedMacKey, $decrypted, $privateKey);

上面的$decrypted 包含一些二进制数据,所以我不确定是否需要将其转换为字节数组或将其视为字符串...


第 2 部分。

每个请求都有一个counter。上面 Java 代码中的 macKey 用于从 counter 中创建 MAC 值。

下面的Java代码sn-p在PHP中的等价物是什么?

int counter = 0;
String nextCounter = String.valueOf(++counter);
SecretKeySpec signingKey = new SecretKeySpec(macKey, "AES");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] counterMac = mac.doFinal(nextCounter.getBytes("UTF-8"));
String base64EncodedMac = DatatypeConverter.printBase64Binary(counterMac);

上面的base64EncodedMac最终被发送到设备验证通信。

我尝试在谷歌上搜索不同的解决方案,但是我未能成功地在 PHP 中生成有效的 base64EncodedMac 字符串以供设备批准。

【问题讨论】:

    标签: java php encryption


    【解决方案1】:

    自己找到了解决方案。对于第 1 部分,我选择使用phpseclib 来生成公钥/私钥并指定加密算法。解密macKey

    $rsa = new Crypt_RSA();
    $keys = $rsa->createKey(2048);
    // [...]
    
    $macKey = base64_decode($base64EncodedMacKey);
    
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
    $rsa->loadKey($keys['privatekey']);
    $decryptedMac = $rsa->decrypt($macKey);
    

    接下来是第 2 部分:

    $counter = 0;
    $hmac = hash_hmac('sha256', ++$counter, $decryptedMac, true);
    $counterMac = base64_encode($hmac);
    

    主要令人困惑的部分是,在 Java 中,HMAC 是由字节数组完成的,而在 PHP 中,hash_hmac 函数需要一个字符串作为其第二个参数,因此使用 unpack() 是不够的。但是,它似乎可以直接传递$counter。使用第 4 个参数作为 TRUE 返回原始数据也很重要。

    【讨论】:

      猜你喜欢
      • 2016-08-18
      • 2011-11-07
      • 2014-10-16
      • 2011-08-13
      • 2018-04-08
      • 2011-11-06
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多