我在使用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公开的box
和secretbox
构造不需要额外的填充。密文直接返回,之前没有16个额外的字节。可以直接给出该消息,而无需添加16个nul字节。
TweetNaclFast不需要任何填充,但是libsodium-net显然需要。
使用libsodium-net观察的密文之前的多余16个字节不包含任何有用的信息。只是一堆零。您可以安全地剥离它们,并在以后调用Sodium.SecretBox.Open
时添加它们。
请注意,与Sodium.SecretBox
不同,Sodium.PublicKeyBox
不需要填充。