1

libsodium-net ライブラリを使用して C# で Nacl SecretBox (TweetNaclFast ライブラリを使用して Java で生成) を開く際に問題が発生しています。また、その逆もできません (TweetNaclFast を使用して、libsodium-net で生成されたボックスを開きます)。

次の例では、TweetNaclFast (Java) を使用して SecretBox を作成し、libsodium-net (C#) でそれを開こうとします。

SecretBox の作成 (Java)

    String secretMessage = "Hello Stack overflow!";
    byte[] messageBytes = secretMessage.getBytes("UTF-8");
    byte[] keyBytes = secureRandomGenerator(); //returns 32 random bytes (256 bits)
    byte[] nonceBytes = TweetNaclFast.makeSecretBoxNonce();

    byte[] boxBytes = new TweetNaclFast.SecretBox(keyBytes).box(messageBytes,nonceBytes);

    System.out.println("Base64 box -> "+Base64.encodeBase64String(boxBytes));
    System.out.println("Base64 key -> "+Base64.encodeBase64String(keyBytes));
    System.out.println("Base64 nonce -> "+Base64.encodeBase64String(nonceBytes));

作成出力

Base64 box -> iNEpgwFIo6nyaLNgMpSWqwTQ9Z5y/y+BUXszXVFZ2gP2A3XJ0Q==
Base64 key -> FKpCo/AhRRUjdQIpzMbZSnnzfBx1e/Ni9VZyNWYEB8E=
Base64 nonce -> 2qngWbMLFVNiPTFqTVO9nsraB8ACIrwV

SecretBox を開く (C#)

string box = "iNEpgwFIo6nyaLNgMpSWqwTQ9Z5y/y+BUXszXVFZ2gP2A3XJ0Q==";
string key = "FKpCo/AhRRUjdQIpzMbZSnnzfBx1e/Ni9VZyNWYEB8E=";
string nonce = "2qngWbMLFVNiPTFqTVO9nsraB8ACIrwV";


        try
        {
            byte[] message = Sodium.SecretBox.Open(
            Convert.FromBase64String(box),
            Convert.FromBase64String(nonce),
            Convert.FromBase64String(key));

            Console.WriteLine(Encoding.UTF8.GetString(message));
        }
        catch (CryptographicException e)
        {
            Console.WriteLine(e.Message);
            Console.WriteLine(e.StackTrace);
        }

出力を開く

Failed to open SecretBox
   at Sodium.SecretBox.Open(Byte[] cipherText, Byte[] nonce, Byte[] key)

私が間違っているかもしれないことについて何か考えはありますか?


編集

問題はライブラリの1つにあると思います(libsodium-netが最も可能性が高い)。同じ変数で SecretBox を作成すると、別のボックスが得られます...

TweetNaclFastで秘密箱を作る

String message = "Hello Stack overflow!";
String key = "uCEgauAQDWGDkcclGe1rNV6V77xtizuemhgxzM5nqO4=";
String nonce = "+RTDstWX1Wps5/btQzSMHWBqHU9s6iqq";

SecretBox box = new SecretBox(Base64.decodeBase64(key));
byte[] cipherText = box.box(message.getBytes("UTF-8"), Base64.decodeBase64(nonce));

戻り値: yDCt/kOLFUWPZpV3deVNUZaH0ZHLVmj9Nvm8QlbVKPe1a/INDw==

libsodium-netで秘密箱を作る

string message = "Hello Stack overflow!";
string key = "uCEgauAQDWGDkcclGe1rNV6V77xtizuemhgxzM5nqO4=";
string nonce = "+RTDstWX1Wps5/btQzSMHWBqHU9s6iqq";

byte[] box = Sodium.SecretBox.Create(Encoding.UTF8.GetBytes(message), 
                                             Convert.FromBase64String(nonce), 
                                             Convert.FromBase64String(key));

Console.WriteLine(Convert.ToBase64String(box));

戻り値: AAAAAAAAAAAAAAAAAAAAAMgwrf5DixVFj2aVd3XlTVGWh9GRy1Zo/Tb5vEJW1Sj3tWvyDQ8=

4

2 に答える 2

0

ドキュメント (RTFM) を読むべきだった... どうやら libsodium-net は、暗号文の先頭に 16 バイトの認証タグを追加します ( https://bitbeans.gitbooks.io/libsodium-net/content/secret-key_cryptography/authenticated_encryption. html )。最初の 16 バイトを削除すると、TweetNaclFast SecretBox と同じ出力が得られます。

string message = "Hello Stack overflow!";
string key = "uCEgauAQDWGDkcclGe1rNV6V77xtizuemhgxzM5nqO4=";
string nonce = "+RTDstWX1Wps5/btQzSMHWBqHU9s6iqq";

byte[] box = Sodium.SecretBox.Create(Encoding.UTF8.GetBytes(message), 
                                             Convert.FromBase64String(nonce), 
                                             Convert.FromBase64String(key));

byte[] boxWithoutAuthenticationTag = new byte[box.Length - 16];
Array.Copy(box, 16, boxWithoutAuthenticationTag, 0, box.Length - 16);
Console.WriteLine(Convert.ToBase64String(boxWithoutAuthenticationTag));

返されるようになりました: yDCt/kOLFUWPZpV3deVNUZaH0ZHLVmj9Nvm8QlbVKPe1a/INDw==


最初の例のシークレット ボックスを開く (復号化する) には、次のコードを使用します。

string box = "iNEpgwFIo6nyaLNgMpSWqwTQ9Z5y/y+BUXszXVFZ2gP2A3XJ0Q==";
string key = "FKpCo/AhRRUjdQIpzMbZSnnzfBx1e/Ni9VZyNWYEB8E=";
string nonce = "2qngWbMLFVNiPTFqTVO9nsraB8ACIrwV";

try
{
    //Libsodium-net SecretBox.Open() requires a 16 byte authentication tag at the start of the ciphertext
    //TweetNaclFast boxing method does not append a 16 byte authentication tag anywhere
    //Thus, we need to add a 16 byte authentication tag at the start of ciphertext encripted by TweetNaclFast
    byte[] authenticationTag = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //Zeroed 16 Bytes Authentication Tag
    byte[] tweetNaclFastCiphertextBytes = Convert.FromBase64String(box);
    byte[] libsodiumNetLikeCiphertext = new byte[tweetNaclFastCiphertextBytes.Length + authenticationTag.Length];
    Array.Copy(authenticationTag, libsodiumNetLikeCiphertext, authenticationTag.Length);
    Array.Copy(tweetNaclFastCiphertextBytes, 0, libsodiumNetLikeCiphertext, authenticationTag.Length, tweetNaclFastCiphertextBytes.Length);
    byte[] nonceBytes = Convert.FromBase64String(nonce);
    byte[] keyBytes = Convert.FromBase64String(key);

    Console.WriteLine(Encoding.UTF8.GetString(Sodium.SecretBox.Open(libsodiumNetLikeCiphertext, nonceBytes, keyBytes)));
}
catch (CryptographicException e)
{
    Console.WriteLine(e.Message);
    Console.WriteLine(e.StackTrace);
}

これで、 Hello スタック オーバーフローが返されるはずです。

于 2016-04-16T22:53:17.683 に答える