代码之家  ›  专栏  ›  技术社区  ›  Zaki Aziz

“格式错误的UTF-8字符”错误时,尝试json_编码和数组保存一些加密值

  •  0
  • Zaki Aziz  · 技术社区  · 6 年前

    我需要将一些JSON数据发送到一个API端点,该端点要求对请求的部分进行加密。我有一个由API提供程序提供给我的公钥。以下是相关代码:

    $key = "-----BEGIN PUBLIC KEY-----
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    -----END PUBLIC KEY-----";
    
    openssl_public_encrypt('my_username', $username, openssl_pkey_get_public($key));
    openssl_public_encrypt('my_pa55w0rd', $password, openssl_pkey_get_public($key));
    
    $client = new GuzzleHttp\Client();
    $result = $client->post(
        'https://api.domain.com/endpoint',
        [
            'headers' => [
                'Authorization' => 'Bearer ' . $bearerToken,
                'Content-Type' => 'application/json',
            ],
            'json' => [
                'username' => $username,
                'pasword' => $password,
                'unencrypted_key' => 'an unencrypted value,
            ]
        ]
    );
    

    json_encode error: Malformed UTF-8 characters, possibly incorrectly encoded 错误。当你做 echo $username; malformed encrypted string

    我不确定我做错了什么,也不知道是否有其他方法可以在值被json编码之前对其进行加密。

    注: json_encode 在发送请求之前。

    0 回复  |  直到 6 年前
        1
  •  3
  •   Scott Arciszewski    6 年前

    作为 msg

    openssl_public_encrypt 返回一个二进制流,这是损坏的输出,您需要先用ascii编码,可能是 base64_encode 但是,如果传输已经使用ssl,为什么还需要加密呢?请与api提供商联系。

    然而,也有可能他们希望得到十六进制编码的数据。给予 bin2hex() 试试看吧。

    如果他们有其他奇怪的格式(Base32Hex?),请随意使用 this RFC 4648 library 对你的信息进行编码。


    这不是你问题的答案,但是你和你的API都应该知道。

    openssl公共加密 默认为RSA with PKCS#1 v1.5填充,它容易受到 a padding oracle attack .

    至少:与您通信的API的开发人员应该停止接受用RSA加密的PKCS v1.5填充的数据,而只接受OAEP密文。

    在那里 ways to work around Bleichenbacher's 1998 attack

    但是,由于其他原因,RSA加密非常混乱: You can't encrypt large messages directly with RSA .

    还有 plenty of other ways RSA can go wrong .

    建议

    更好的解决方案是完全停止使用RSA。

    has bindings in most popular programming languages (包含在php7.2内核中)和 makes this easier to get right

    // On your end...
    $sendToProvider = sodium_bin2hex(
        sodium_crypto_box_seal($privateData, $publicKey)
    );
    
    // On their end...
    $decrypted = sodium_crypto_box_seal_open(
        sodium_hex2bin($encrypted),
        $keypair
    );
    

    无论如何,您都会遇到编码问题(因为这两个api都返回原始二进制字符串)。然而,使用lib钠可以避免很多安全问题,直到你读到这个StackOverflow的答案你才知道。

    还有:如果你不知道就不要难过。你并不孤单。甚至Zend框架的密码库 got bit by these RSA vulnerabilities 他们和恩里穆尔在他们的团队里。RSA对于现实世界的密码来说是一个糟糕的选择。

    推荐文章