将 base64 编码的字符串转换为 swift 中的普通字符串 3

Convert base64-encoded string to normal string in swift 3

我想转换以下 base64 编码的 String in Swift 3:

dfYcSGpvBqyzvkAXkdbHDA==

与其等价的String

uöHjo¬³¾@‘ÖÇ

以下网站做得很好:

http://www.motobit.com/util/base64-decoder-encoder.asp

http://www.utilities-online.info/base64/#.WG-FwrFh2Rs

PHP 的函数 base64_decode 也是如此。这个函数的documentation表示:

Returns FALSE if input contains character from outside the base64 alphabet.

但我无法在 Swift 中做同样的事情 3. 以下代码也无法完成工作:

func convertBase64ToNormalString(base64String:String)->String!{
   let decodedData = Data(base64Encoded: base64String, options:    Data.Base64DecodingOptions())
   let bytes = decodedData?.bytes
   return String(bytes: bytes, encoding: NSUTF8StringEncoding)
}

这里是关于为什么我需要将 base64 字符串转换为字符串的上下文信息: 我的 Php 开发人员要我发送所有使用 AES 算法加密的 API 参数值。为此,我使用 this lib。 他给了我十六进制格式的 AES 密钥(我在 中提到)和 base64 中的 iv(上面给出),他指示我在使用前解码这个 base64 密钥,因为他也在他的 [=51 中做同样的事情=] 代码。这是他的PHP加解密代码:

function encryptParamAES($plaintext, $encryptionEnabled = true) {
    if (! $encryptionEnabled) {
        return $plaintext;
    }
    // --- ENCRYPTION ---

    // Constants =========================================================
    // the key should be random binary, use scrypt, bcrypt or PBKDF2 to
    // convert a string into a key
    // key is specified using hexadecimal
    $key = pack ( 'H*', "dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4" );
    // create a random IV to use with CBC encoding
    $iv_size = 16;
    $iv = base64_decode ( "dfYcSGpvBqyzvkAXkdbHDA==" );

    // End Of constants ===================================================

    // echo "IV: " . base64_encode ( $iv ) . "\n<br>";
    // echo "IV Size: " . $iv_size . "\n<br>";

    // show key size use either 16, 24 or 32 byte keys for AES-128, 192
    // and 256 respectively

    // $key_size = strlen ( $key );
    // echo "Key size: " . $key_size . "\n<br><br>";

    // creates a cipher text compatible with AES (Rijndael block size = 128)
    // to keep the text confidential
    // only suitable for encoded input that never ends with value 00h
    // (because of default zero padding)
    $ciphertext = mcrypt_encrypt ( MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv );

    // prepend the IV for it to be available for decryption
    $ciphertext = $iv . $ciphertext;

    // encode the resulting cipher text so it can be represented by a string
    $ciphertext_base64 = base64_encode ( $ciphertext );

    return $ciphertext_base64;
}


function decryptParamAES($ciphertext_base64, $encryptionEnabled = true) {
    if (! $encryptionEnabled) {
        return $ciphertext_base64;
    }
    // --- DECRYPTION ---

    // Constants =========================================================
    // the key should be random binary, use scrypt, bcrypt or PBKDF2 to
    // convert a string into a key
    // key is specified using hexadecimal
    $key = pack ( 'H*', "dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4" );
    // create a random IV to use with CBC encoding
    $iv_size = 16;
    $iv = base64_decode ( "dfYcSGpvBqyzvkAXkdbHDA==" );

    // End Of constants ===================================================

    $ciphertext_dec = base64_decode ( $ciphertext_base64 );

    // retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
    $iv_dec = substr ( $ciphertext_dec, 0, $iv_size );

    // retrieves the cipher text (everything except the $iv_size in the front)
    $ciphertext_dec = substr ( $ciphertext_dec, $iv_size );

    // may remove 00h valued characters from end of plain text
    $plaintext_dec = mcrypt_decrypt ( MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec );
    return rtrim ( $plaintext_dec );
}

我刚看到这段 PHP 代码,想知道为什么他不使用 $iv 作为 mcrypt_decrypt 函数的最后一个参数!!会更新你的。但是问题还是一样,PHP 函数 base64_decode 不会 return FALSE 对于上面的 base64 字符串! 我自己通过终端命令测试了这个功能:php test.php。这里 test.php 包含以下代码:

<?php
$iv = base64_decode ( "dfYcSGpvBqyzvkAXkdbHDA==" );
echo $iv;
?>

输出为:u?Hjo???@???

查看您修改后的问题,您正在尝试使用此 base-64 字符串,并将其用作 AES 算法中的 iv。我能理解您为什么想知道如何将结果 Data 转换为 String,但您不应该那样做。是的,有一个 AES 的演绎版,它期望 iv 作为一个字符串。但还有另一种演绎形式需要 Array<UInt8>。所以,就像 MartinR 在 中所说的那样,改为构建一个 UInt8 的数组,如下所示:

let iv = Array(Data(base64Encoded: "dfYcSGpvBqyzvkAXkdbHDA==")!)

结果 ivArray<UInt8>(也称为 [UInt8])。您可以将其与 AES 函数一起使用。

我最初关于将 Data 对象转换为 UTF8 字符串的讨论如下。但关键信息是您不应该尝试这样做。只需构建您的 UInt8 数组并将其与您的库的 AES 函数一起使用。


查看您的其他问题 (),您在评论中透露您正在处理 AES 密钥。我怀疑我们在这里处理类似的问题(虽然那是 32 字节的数据,而这里我们有 16 字节)。

最重要的是,我建议您完全放弃此 "how to I get a string representation of the data captured in this base-64 string" 询问行。如果它是加密密钥(或某种令牌或其他),请不要试图将其表示为字符串。 (这是 base-64 的 存在理由,用于创建非字符串数据的可传输字符串表示。)

我建议您退后一步,描述您要解决的更广泛的问题。停止尝试从这些二进制有效负载中创建字符串。在您的代码片段中,您成功地从 base-64 字符串创建了一个 Data。我认为真正的问题不是 "how do I now get a string from that?",而是 "what do I do this Data?"

如果没有关于您从何处获得这些数据及其用途的更多背景信息,我们无法回答该问题。

顺便说一句,我对你的问题的原始回答如下。


问题是 base-64 字符串转换为 16 字节的数据,其十六进制表示为

75f61c48 6a6f06ac b3be4017 91d6c70c

但该负载不是有效的 UTF8 字符串。第三个字节,1c与UTF8字符串不一致。如果你看definition of UTF8,它说如果一个字节在f6-fb范围内,也就是第二个字节,那么这个字符由那个和后面两个组成字节,两者都应该在217ea0ff范围内,而1c不是。

所以,这根本不是有效的 UTF8 字符串。很明显,您使用的那些网站并不优雅 detecting/handling 无效的 UTF8 字符串。

可能此 base-64 字符串中的数据是从使用不同编码的字符串转换而来的。或者,也许它本来就不是字符串。并非所有二进制有效负载都具有干净的字符串表示形式。坦率地说,这就是我们首先使用 base-64 表示的原因,以提出不是字符串的数据块的文本表示。

如果您提供有关此 base-64 字符串中包含的数据源的更多信息,我们也许可以为您提供进一步的建议。