我在使用libsodium-net库在C#中打开Nacl SecretBox(在Java中使用TweetNaclFast库生成)时遇到问题。
我也无法做到这一点(使用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)


关于我可能在做错的任何想法吗?



编辑

我猜问题出在其中一个库中(最有可能是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 =

最佳答案

Sodium.SecretBox.Create使用原始的NaCl crypto_box() API,在消息和密文之前需要额外的填充。

这个API有点混乱,除了在C语言中很少使用。即使在C语言中,使用它的人也最终写出包装程序来填充或删除填充。

大多数API公开的boxsecretbox构造不需要额外的填充。密文直接返回,之前没有16个额外的字节。可以直接给出该消息,而无需添加16个nul字节。

TweetNaclFast不需要任何填充,但是libsodium-net显然需要。

使用libsodium-net观察的密文之前的多余16个字节不包含任何有用的信息。只是一堆零。您可以安全地剥离它们,并在以后调用Sodium.SecretBox.Open时添加它们。

请注意,与Sodium.SecretBox不同,Sodium.PublicKeyBox不需要填充。

10-06 09:48