在 PHP 中解密 OpenEdge 加密字符串 (AES-128)


Decrypt an OpenEdge-encrypted String (AES-128) in PHP

这是我在OpenEdge 10.1B中使用的函数,用于使用AES-128 OFB加密字符串:

 DEFINE VAR cRes AS CHAR INITIAL ? NO-UNDO.
 DEFINE VAR rKey AS RAW NO-UNDO.
 DEFINE VAR rEnc AS RAW NO-UNDO
 rKey = GENERATE-PBE-KEY(cEncKey).
 eEnc = ENCRYPT(cData, rKey, ?, "AES_OFB_128").
 cRes = BASE64-ENCODE(rEnc) NO-ERROR.
 IF ERROR-STATUS::ERROR THEN cRes = ?.
 return cRes.

此功能可以很好地加密。

当我想使用以下 PHP 解密它时,它会失败,例如,它给了我与原始字符串不同的结果。

// decrypted: original string is supposed to have 33 characters
$encrypted = "YnRvNjIG1kj1QtUM9ZYuVYS3D4LBYCEsprjg2QCaD/eM";
$key = "27Zkp6Wq";
$method = 'aes-128-ofb';
# do decryption
echo "<pre>".openssl_decrypt(base64_decode($encrypted), $method, $key, false)."</pre>";

我知道这可能与 GENERATE-PBE-KEY 函数有关,但我看不到如何在 PHP 中生成 PCKS#5 密钥。

有人可以帮我吗?

这太长了,无法发表评论。需要注意的几件事:

  1. openssl_decrypt的第四个参数应true或第一个参数应保留 base64 编码。除非是双基64编码:)

  2. 密钥
  3. base64 是编码的还是原始密钥?

  4. 从OpenEdge来看,是否将PBES1 (pbkdf1)PBES2 (pbkdf2)应用于密钥并不完全清楚,但默认设置使用sha1作为哈希算法,没有盐和1000作为迭代计数。您可以在线找到 PHP 实现示例。

摆弄了你的例子后,我无法让它工作,但上面应该引导你朝着正确的方向前进; 顺便说一句,当我尝试在 PHP 中执行编码步骤时,它导致了一个更短的加密字符串......我不知道该怎么看待这个:)

您是否在任何地方定义了 SECURITY-POLICY:PBE-HASH-ALGORITHM 和 SECURITY-POLICY:PBE-KEY-ROUNDS?

http://documentation.progress.com/output/OpenEdge102b/pdfs/dvpin/dvpin.pdf#page=173

好吧,所以我终于放弃了。问题显然是OpenEdge中的哈希函数,我未能在PHP中重现。解决方案是从哈希函数中获取哈希密钥,并通过第二个通道将其以十六进制形式移动到PHP,以使用它进行解密。

不是完全安全的,它不优雅,但它有效,我们的安全问题不是代码端,而是数据库存储端。您的要求可能有所不同,因此请仅在确定此方法可用时才使用此方法。

在OpenEdge代码中,您应该更改:

rKey = GENERATE-PBE-KEY(cEncKey)

自:

rKey = MESSAGE-DIGEST('SHA-256', cEncKey)

在PHP代码中,你应该使用:

$key = substr(hash('sha256', $cEncKey, true), 0, 32);

你会让它工作。