ektrah / nsec Goto Github PK
View Code? Open in Web Editor NEWA modern and easy-to-use cryptographic library for .NET 8+ based on libsodium
Home Page: https://nsec.rocks
License: MIT License
A modern and easy-to-use cryptographic library for .NET 8+ based on libsodium
Home Page: https://nsec.rocks
License: MIT License
Will be very suitable to use it with alpine runtime
Question: how come the Argon2i function/scrypt functions from https://libsodium.gitbook.io/doc/password_hashing/the_argon2i_function are not exposed in the main library? It would be very useful and they are seemingly passing their tests?
The current state of libsodium bindings for .NET is a mess. For example, here's the date of the last commit in each repo:
Besides ASodium, which was only recently developed, all of these bindings are no longer being maintained. I would also argue that it's unlikely that ASodium will be maintained in the long-term like NSec has been. Furthermore, these implementations have awful naming in my opinion and don't employ the memory protection that NSec does. Therefore, at first glance, it seems that NSec is the best libsodium binding for .NET.
However, NSec doesn't support a lot of the algorithms available in libsodium, which is a serious problem considering that it's really the only maintained binding. I completely understand why for some of them (e.g. not supporting unauthenticated ChaCha20 to encourage AEAD use, although that's unfortunate for building custom constructions), but others should be present. For instance, as briefly discussed in #27, there's no password-based KDF (aka there's no Argon2). Several of your arguments for not adding Argon2 simply don't hold up. For the parameter selection, you could just encourage the libsodium defaults and enforce sensible lower limits for the memory size and iterations. The algorithm has received wide adoption at this point, so it frankly doesn't matter whether the RFC is in the draft stage or not. Lastly, I don't see how dealing with out-of-memory exceptions is an issue when none of the other bindings seem to consider it to be a problem.
Another algorithm that should be added is XChaCha20-Poly1305, which is again widely used at this point and a more sensible option than ChaCha20-Poly1305 in many cases. I suspect your argument for not adding this is that the RFC is again in the draft stage. However, that RFC isn't very good anyway since it specifies a smaller counter than libsodium and Monocypher. Moreover, if an algorithm is accessible in libsodium, then it's probably being used, which is what's important rather than whether or not something has an RFC, especially considering how difficult it is to write an RFC and get it past the draft stage.
Then there's no secretstream support, which would save people the hassle of implementing their own stream encryption, not to mention the mistakes that often brings. There's also no crypto_box support despite that being quite popular from what I've seen, although I can understand not including this since it does rely on XSalsa20-Poly1305. There's only HKDF support rather than support for the default KDF in libsodium (salted BLAKE2b). The recommendation for generating random bytes/numbers is to use System.Security.Cryptography.RandomNumberGenerator rather than providing simple functions for libsodium, which would save people a few lines of code. Finally, there doesn't seem to be any constant time functions, and there's no padding function.
In sum, a lot of very useful algorithms in libsodium appear to be missing without justification for their absence. I can understand wanting to keep the library small, but the lack of a password-based KDF, especially when the only one available in .NET is PBKDF2, is ridiculous and so is the fact that XChaCha20-Poly1305 is missing. The presence of most of the other functions I've discussed more or less comes down to whether or not this library is trying to prevent people from making mistakes, which is implied by the 'NSec wants you to fall into the pit of success' claim.
PS, I apologise if I've made any inaccurate claims about the library. I haven't actually used NSec besides benchmarking the HKDF implementation because it doesn't include algorithms like Argon2 and XChaCha20.
Hi there, this is not an issue but rather a solution to a problem i had and i was thinking of share here to keep in the closed issues historic for future references.
I managed to make NSec work in Net Standard 2.0 under Unity 3D with some modifications and compiling the Libsodium libraries.
Here is the repo with the branch in case anyone needs, it's based in the version 19.5.0 but i think there is no issue with updating to the latest if anyone needs it.
https://github.com/Kirbyrawr/nsec-unity/tree/19.5.0-unity
Tried in Android and PC and works ok, should work for the rest of the platforms considering the Libsodium libraries are there.
Have you considered releasing pre .NET Standard 2.0?
The .NET Core roadmap states 2.0 release is slated for Q3 2017, and this seems like an aweful long time to wait. I'm building a .NET Core Discord client (I am aware of Discord.NET - this is different), and would love to use this library.
bitcoin uses RIPEMD160, SHA256, ECDSA on Secp256k1 curve
Does this library support these algorithms?
Hello,
I have a program that already signs with Ed25519. Currently I am using a different library for that which allows providing a byte array as a private key to sign data. I consider transitioning to this library instead but would like to keep using the old private key. Should I be able to create a "Key" object with my own private key as a byte array?
As far as I can tell you cannot sign with X25519, and you cannot generate a shared secret and key with Ed25519. I do not want to create 2 different keys, if possible. Thanks!
I'm putting together a .NET Core Discord client, and the voice connection requires raw opus stream encoded using xsalsa_poly1305
.
https://discordapp.com/developers/docs/topics/voice-connections
Not being a crypto guy myself, I am new to NaCl, libsodium, etc, and have stupid questions to ask:
xsalsa_poly1305
?๐
Libsodium's crypto_kx_client_session_keys() function wrap calls to crypto_scalarmult
and crypto_generichash
in to a single place to provide tx
and rx
keys using Blake2b and is quite distinct from the existing KeyAgreementAlgorithm
and KeyDerivationAlgorithm
classes in NSec.
Are there any plans to support the libsodium key exchange API in NSec?
I think an implementation of DHKE would be a great addition to this library. I've been able to replace bouncy castle with it for all aspects except for this. This might already be implemented by https://nsec.rocks/docs/api/nsec.cryptography.keyagreementalgorithm
but it's hard to read from the documentation
In the API documentation, section AEAD -> encrypt there is a hint about using random values as nonce:
To prevent nonce reuse when encrypting multiple plaintexts with the same key, it is recommended to increment the previous nonce; a randomly generated nonce is not suitable.
This statement surprised me, and I'm unable to find sources that support the claim that random nonces are insecure. I was under the impression that random nonces are secure if a cryptographically secure random number generator is used.
Could you clarify why (or in which cases) random nonces are insecure?
https://tools.ietf.org/html/rfc7748#section-6.2
Bit overkill, but assume performance isn't an issue.
Hi,
I'd like to play with the code, but I'm struggling trying to compile it.
In particular, it seems the two nuget dependencies cannot be restored. (System.Memory [4.5.0-preview2-26228-08] and System.Runtime.CompilerServices.Unsafe [4.5.0-preview2-26228-08])
I suspect this is because these are pre-release versions that are not yet available on nuget.org.
I see in the build script some references to dotnet.myget.org, but simply adding this package source in my visual studio does not seem to resolve the issue...
Could offer some guidance please?
(And in the future, I suggest you adhere to the F5 manifesto, if at all possible :) )
Thank you.
I was wondering if there was any way to generate the same shared secret through different keypairs because the following code that I write when I compare it to other shared secret as shown in the code below always giving the output of "false" or do I not need to do the equal comparison in the first place as the shared secret will always be working and the same?
var algorithm = KeyAgreementAlgorithm.X25519;
var creationParameters = new KeyCreationParameters
{
ExportPolicy = KeyExportPolicies.AllowPlaintextExport
};
var key = Key.Create(algorithm,creationParameters);
var key2 = Key.Create(algorithm,creationParameters);
var client_key_1 = key;
var client_Pkey_1 = PublicKey.Import(algorithm, key2.Export(KeyBlobFormat.NSecPublicKey),KeyBlobFormat.NSecPublicKey);
var client_key_2 = key;
var client_Pkey_2 = PublicKey.Import(algorithm, key.Export(KeyBlobFormat.NSecPublicKey), KeyBlobFormat.NSecPublicKey);
var sharedsecret = KeyAgreementAlgorithm.X25519.Agree(client_key_1,client_Pkey_1);
var sharedsecret2 = KeyAgreementAlgorithm.X25519.Agree(client_key_2, client_Pkey_2);
Console.WriteLine(sharedsecret.Equals(sharedsecret2));
Any help will be appreciated and can I do signing with KeyAgreementAlgorithm?
I am trying to debug NSec failing at runtime because it cannot find libsodium on Windows, using Visual Studio 2019.
I have downloaded from master, built a nupkg. I start a new C# project, make a custom package source with a directory containing this nupkg. Then I can install the nupkg into the repo if I check "Include prerelease".
After installing, the path attribute of the "NSec.Cryptography" item in the dependencies listing of the Solution Explorer is "C:\Users\janus\source\repos\ConsoleApp1\packages\NSec.Cryptography.19.10.0-preview1-28213-71\lib\netstandard2.0\NSec.Cryptography.dll".
When running the application with has a Main simply containing NSec.Cryptography.AeadAlgorithm.ChaCha20Poly1305.Encrypt(null, new NSec.Cryptography.Nonce(), null, null);
, I get:
Unhandled Exception: System.PlatformNotSupportedException: Could not initialize platform-specific components. NSec may not be supported on this platform. See https://nsec.rocks/docs/install for more information. ---> System.DllNotFoundException: Unable to load DLL 'libsodium': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at Interop.Libsodium.sodium_library_version_major()
at NSec.Cryptography.Sodium.InitializeCore()
--- End of inner exception stack trace ---
at NSec.Cryptography.Sodium.InitializeCore()
at NSec.Cryptography.Sodium.Initialize()
at NSec.Cryptography.Algorithm..ctor()
at NSec.Cryptography.AeadAlgorithm..ctor(Int32 keySize, Int32 nonceSize, Int32 tagSize)
at NSec.Cryptography.ChaCha20Poly1305..ctor()
at NSec.Cryptography.AeadAlgorithm.get_ChaCha20Poly1305()
at ConsoleApp1.Program.Main(String[] args) in C:\Users\janus\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 13
Now, I see there is a libsodium package on Nuget, but I tried something else, I dunno if it makes sense: I downloaded msys2, installed mingw-w64-i686-gcc
and make
and I was able to build libsodium from source. So I copy libsodium-23.dll
into the build directory with a simpler name:
cp src/libsodium/.libs/libsodium-23.dll /c/Users/janus/source/repos/ConsoleApp1/ConsoleApp1/bin/Debug/libsodium.dll
And now I get:
Unhandled Exception: System.InvalidOperationException: An error occurred while initializing cryptographic primitives.
at NSec.Cryptography.Sodium.InitializeCore()
at NSec.Cryptography.Sodium.Initialize()
at NSec.Cryptography.Algorithm..ctor()
at NSec.Cryptography.AeadAlgorithm..ctor(Int32 keySize, Int32 nonceSize, Int32 tagSize)
at NSec.Cryptography.ChaCha20Poly1305..ctor()
at NSec.Cryptography.AeadAlgorithm.get_ChaCha20Poly1305()
at ConsoleApp1.Program.Main(String[] args) in C:\Users\janus\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 13
My apologies if I missed it somewhere -> is this currently implemented?
https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519
libsodium-net has PasswordHash.ArgonHashString with enum parameter (e.g. Strength.Interactive) and PasswordHash.ArgonHashStringVerify methods .
Does nsec has similar class? If it is available ,is it compatible, i.e. can I hash using one library and un-hash using other library?
I want in .Net/.Net Core do something like the following
// Hashing a password
var hash = PasswordHash.ArgonHashString(yourPasswordString, Strength.Interactive)
if (PasswordHash.ArgonHashStringVerify(hash, yourPasswordString) {
//correct password
}
I am new to using these cryptographic algorithms, maybe I am doing something wrong ..
Hi i have a problem, i want encrypt and decrypt data using ChaCha20Poly1305... and a SharedSecret with a public/private key but i have a error when import a public key
public EService()
{
var _algoritm = new ChaCha20Poly1305();
var privateKey = Convert.FromBase64String("base64string");
var publicKey = Convert.FromBase64String("base64string");
var _privateKey = Key.Import(_algoritm, privateKey, KeyBlobFormat.RawSymmetricKey);
**/// same bug here!**
var _publicKey = PublicKey.Import(_algoritm, publicKey, KeyBlobFormat.RawSymmetricKey);
var _box = KeyAgreementAlgorithm.X25519.Agree(_privateKey, _publicKey);
var _derived = KeyDerivationAlgorithm.HkdfSha512.DeriveKey(_box, ReadOnlySpan<byte>.Empty,
ReadOnlySpan<byte>.Empty, AeadAlgorithm.ChaCha20Poly1305,
new KeyCreationParameters
{
ExportPolicy = KeyExportPolicies.AllowPlaintextArchiving
});
}
Here is reference to widely used library in Java.
https://github.com/str4d/ed25519-java/blob/master/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java
Their public formater seems to be different:
from your implementation of s_pkixPublicKeyFormatter
Also how does one gets various elements, like group A as in Java implementation.
Hey @ektrah @joemphilips
Key generation is an important part of cryptographic library. User may want to generate same key multiple times, hence "seed" plays an important role. Internal functions support seed as an option but it is a randomly generated one in current implementation as far as I can see. Please correct.
Accepting seed from the user can be a useful feature to implement. Please give your opinion on this.
Below is the existing code reference :
Regards,
Rinkal Bhojani
Once the key generated, how do I get private key to store it?!
Hi,
I'm trying to use NSec with Xamarin Forms, but I'm having some trouble. The library doesn't load.
Anybody can help me, please?
Thanks
System.TypeInitializationException: The type initializer for 'BizPay.Crypto.CryptoHelper' threw an exception. ---> System.PlatformNotSupportedException: Could not initialize platform-specific components. NSec may not be supported on this platform. See https://nsec.rocks/docs/install for more information. ---> System.DllNotFoundException: libsodium\n at (wrapper managed-to-native) Interop+Libsodium.sodium_library_version_major()\n at NSec.Cryptography.Sodium.InitializeCore () [0x00000] in :0 \n --- End of inner exception stack trace ---\n at NSec.Cryptography.Sodium.InitializeCore () [0x0003e] in :0 \n at NSec.Cryptography.Sodium.Initialize () [0x00007] in :0 \n at NSec.Cryptography.Algorithm..ctor () [0x00006] in :0 \n at NSec.Cryptography.SignatureAlgorithm..ctor (System.Int32 privateKeySize, System.Int32 publicKeySize, System.Int32 signatureSize) [0x00000] in :0 \n at NSec.Cryptography.Ed25519..ctor () [0x00000] in :0 \n at NSec.Cryptography.SignatureAlgorithm.get_Ed25519 () [0x00009] in :0 \n at BizPay.Crypto.CryptoHelper..cctor () [0x00000] in /Users/leandrolustosa/Documents/BizWallet/BizPay/BizPay/Crypto/CryptoHelper.cs:13 \n --- End of inner exception stack trace ---\n at BizPay.ViewModels.WalletViewModel+d__26.MoveNext () [0x001fd] in /Users/leandrolustosa/Documents/BizWallet/BizPay/BizPay/ViewModels/WalletViewModel.cs:92 \n--- End of stack trace from previous location where exception was thrown ---\n at BizPay.ViewModels.WalletViewModel+d__26.MoveNext () [0x000cb] in /Users/leandrolustosa/Documents/BizWallet/BizPay/BizPay/ViewModels/WalletViewModel.cs:78 "
var Password = Default.GetBytes("8888888");
var al = AeadAlgorithm.ChaCha20Poly1305;
var key = Key.Import(al,Password,KeyBlobFormat.RawSymmetricKey);
output
Unhandled Exception: System.FormatException: The key BLOB is not in the correct format.
After,I try to use NSecSymmetricKey
,but can't solve this problem.
I am new to crypto library.
Is it possible to save a key derived from a sharedsecret? From what I can tell it tells me it's not a supported format (since the keyformat options are all public/private keys, but a sharedsecret key is symmetric). Is there an easy way to save the key (to avoid recalculating on startup every time)? Thanks.
So confused by this error. As far as I can tell it is none of these issues:
ArgumentException
key.Algorithm is not the same object as the current AeadAlgorithm object. (both are ChaCha20Poly1305)
ArgumentException
nonce.Size is not equal to NonceSize. (don't care about nonce usage, just test encrypting a message. and the exception doesn't mention the nonce)
ArgumentException
plaintext.Length plus TagSize is greater than int.MaxValue. (it's just "hello")
Here is my code:
var algorithm = KeyAgreementAlgorithm.X25519;
using var alice = Key.Create(algorithm);
using var bob = Key.Create(algorithm);
var aliceSharedSecret = KeyAgreementAlgorithm.X25519.Agree(alice, bob.PublicKey);
var bobSharedSecret = KeyAgreementAlgorithm.X25519.Agree(bob, alice.PublicKey);
var aliceSharedSecretKey = KeyDerivationAlgorithm.HkdfSha512.DeriveKey(aliceSharedSecret!, ReadOnlySpan<byte>.Empty, ReadOnlySpan<byte>.Empty, new ChaCha20Poly1305());
var bobSharedSecretKey = KeyDerivationAlgorithm.HkdfSha512.DeriveKey(bobSharedSecret!, ReadOnlySpan<byte>.Empty, ReadOnlySpan<byte>.Empty, new ChaCha20Poly1305());
Console.WriteLine(aliceSharedSecretKey.Algorithm);
Console.WriteLine(bobSharedSecretKey.Algorithm);
var encryptedString = AeadAlgorithm.ChaCha20Poly1305.Encrypt(aliceSharedSecretKey, new Nonce(ReadOnlySpan<byte>.Empty, 1), ReadOnlySpan<byte>.Empty, Encoding.UTF8.GetBytes("Hello").AsSpan());
var encryptedString2 = AeadAlgorithm.ChaCha20Poly1305.Encrypt(bobSharedSecretKey, new Nonce(ReadOnlySpan<byte>.Empty, 2), ReadOnlySpan<byte>.Empty, Encoding.UTF8.GetBytes("Hello").AsSpan());
Console.WriteLine(Convert.ToBase64String(encryptedString));
Console.WriteLine(Convert.ToBase64String(encryptedString2));
I have a feeling it's something to do with my implementation, but the exception message is quite non-descriptive.
Hello,
It's is not an issue per si, but, this repo does not have Discussions tab enabled.
I'm try using the AeadAlgorithm.XChaCha20Poly1305, and I little bit confused when read:
Note
Using the same nonce with the same key more than once leads to catastrophic loss of security.
To prevent nonce reuse when encrypting multiple plaintexts with the same key, it is recommended to increment the previous nonce; a randomly generated nonce is not suitable.
In my scenario I need to encrypt
some data and decrypt
this data in another moment, like an Token
:
>. Request: `my-web-api/token/generate`
>. Response: Some `ciphertext` generated by `XChaCha20Poly1305` in `Base64` format.
But when I tried to use the recommended practices in nonce
value(increment) I can't Decrypt
data. In my thinking I need the suitable nonce
to do the correct data decryption, but, how will I know the appropriate one, if I auto-incremented the value? I need always extern/public
the nonce
I used? Like:
"Encrypt"
>. Request: `my-web-api/token/generate`
>. Response: Some `ciphertext` generated by `XChaCha20Poly1305` in `Base64` format + `nonce`.
"Decrypt"
>. Request: `my-web-api/token/validate`
>. Body: `ciphertext` in `Base64` format with `nonce`.
Some foo
code example:
class Program
{
public static byte[] ExportedKey;
static void Main(string[] args)
{
const string json =
@"{'Id':'62fea73265676bb8c06749a7','TriadKey':'111155555555555555555555555555555555555555555151513321321321654654654897897654654321321112','IsValid':false,'ExpirationDate':'2022-08-19T20:55:14.6146798Z'}";
Aes256Gcm(AeadAlgorithm.Aes256Gcm, "Z8c0kX9ATszSsKCAROHnZw==", json);
Console.ReadLine();
}
private static void Aes256Gcm(AeadAlgorithm aeadAlgorithm, string nonceText, string dataText)
{
// create a new key pair
var creationParameters = new KeyCreationParameters
{
ExportPolicy = KeyExportPolicies.AllowPlaintextArchiving
};
using var key = Key.Create(aeadAlgorithm, creationParameters);
ExportedKey = key.Export(KeyBlobFormat.NSecSymmetricKey);
File.WriteAllBytes("private-secret-key.nsec", ExportedKey);
// generate some data to be signed
var data = Encoding.UTF8.GetBytes(dataText);
var nonce = Encoding.UTF8.GetBytes(nonceText);
// increment nonce
nonce[0]++;
// sign the data using the private key
var ciphertext = aeadAlgorithm.Encrypt(key: key, nonce: nonce, plaintext: data, associatedData: null);
Console.WriteLine($"Encrypted Data:\n{Convert.ToBase64String(ciphertext)}\n");
// DUMB: simulates "new request" `my-web-api/token/validate` = NEW NONCE/INCREMENTED
nonce[0]++;
Decrypt(aeadAlgorithm, nonce, ciphertext);
}
private static void Decrypt(AeadAlgorithm aeadAlgorithm, byte[] nonce, byte[] ciphertext)
{
// re-import it
using var key = Key.Import(aeadAlgorithm, ExportedKey, KeyBlobFormat.NSecSymmetricKey);
var decryptedPlaintext = aeadAlgorithm.Decrypt(key, nonce, default, ciphertext);
Console.WriteLine
(
decryptedPlaintext is null
? "Data decryption failed."
: $"Decrypted Data:\n{Encoding.UTF8.GetString(decryptedPlaintext)}\n"
);
}
}
OUTPUT: "Data decryption failed." - Because use different
nouce
What would be the proper way to deal with this scenario?
Cheers! ๐
Since .NET 4.6.1 is compatible with .NET Standard 2.0, would it be possible to support running on the full .NET framework? I can investigate adding support for this if you'd merge it in,
Hi, I came across this library today and was wondering if updated NuGet packages are hiding somewhere?
I have a blockchain-ish use case where I am signing and verifying data in a byte buffer, which includes storing the public key adjacent to the signature.
Verification is the common operation. With the public key being stored, it would be ideal to be able to verify without having to hit the GC to instantiate a PublicKey
for verification.
I haven't had a chance to dive into the class to see if there are any blockers to switching to ref struct
, but I'm wondering what you think in the meantime?
WebAssembly native dependencies are supported as of .NET 6 - talk demonstrating the capability
It would be great if nsec
could link libsodium in WebAssembly so that the package would work in Blazor!
I am having trouble encrypting a stream of data being read from stdin. I want to have it sit between opening and reading a file. For example, cat test.txt | dotnet encrypt.dll > encrypted.txt
or cat encrypted.txt | dotnet decrypt.dll > decrypted.txt
.
However, every stdin/out code snippet I find for c# uses 2048 byte buffers. For example:
using (Stream stdin = Console.OpenStandardInput())
using (Stream stdout = Console.OpenStandardOutput())
{
byte[] buffer = new byte[2048];
int bytes;
while ((bytes = stdin.Read(buffer, 0, buffer.Length)) > 0)
{
stdout.Write(encrypt_method(buffer), 0, bytes);
}
}
I have it encrypting each chunk of 2048 individually, but it simply fails the decryption bool. I assume it has to do with the 2048 byte chunks, since it works fine if I read the whole file into memory. I'm quite confused, since each 2048 bytes is its own bit of encrypted data. I'm thinking maybe the 2048 byte input is outputting extra bytes for the authentication, causing the input to still read by 2048 bytes, failing. I got that it outputs 2064 bytes, which is 16 bytes for the poly1305. But when I input in chunks of 2064 through stdin, it still fails though. Is there a way to forgo the Poly1305? I have already ignored the nonce, since it would be a hassle with the chunk system. Alternatively, is there a better way for me to encrypt/decrypt a stream of data with this method?
I would appreciate if the code in https://github.com/ektrah/nsec/pull/32/files was merged even if it were in the experimental package and had an extra warning attached. Is there any issues with adding this? I can submit a pull request in a medium amount of time if there are no problems.
In issues/26 you say "if you're generating two keys anyway, why not generate them on the right curve directly?".
AFAIK however, you can generate a single ed25519 keypair, convert the private ed25519 key to a private x25519 key, and the x25519 public key corresponding to the private key can be converted with the ed25519 public key. That's the only way I can make sense of it otherwise projects that use "EdX25519 keys" would make no sense. (https://keys.pub/docs/specs/keys.html#edx25519) (https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519)
This means exchanging a single signature key lets anyone convert the public ed25519 key into a public x25519 key that would correspond to the private x25519 key that would be formed by converting the private ed25519 key to x25519. Unless I have a fundamental misunderstanding of libsodium, of course. ๐คทโโ๏ธ
Hello good day is there any plans for supporting Argon2 password hashing?
Currently, the libsodium version used is hardcoded here and checked here.
This works most of the times because of the dependency on the libsodium nuget package. However, that package doesn't include the libsodium for all potential platforms, and it would be impractical, if at all possible, to do so. For example, here are the bundled versions currently:
./bin/Debug/net5.0/runtimes/win-x86/native/libsodium.dll
./bin/Debug/net5.0/runtimes/linux-x64/native/libsodium.so
./bin/Debug/net5.0/runtimes/win-x64/native/libsodium.dll
./bin/Debug/net5.0/runtimes/osx-x64/native/libsodium.dylib
./bin/Debug/net5.0/runtimes/linux-musl-x64/native/libsodium.so
There's isn't any bundled library for linux on aarch64, so we have to install the library manually somehow. When installing it on linux+aarch64 inside microsoft's docker runtime:5.0
image using apt-get, you get libsodium 1.0.17 instead of 1.0.18.
In my local branch I removed the SODIUM_LIBRARY_VERSION_MINOR
check so it works when using the same major version. Maybe you could allow for overriding the hardcoded version and/or allow to disable the check altogether when an environment variable is set?
Thanks.
The Equals
method implemented on PublicKey
(/src/Cryptography/PublicKey.cs, Line 67) does not appear to check for null prior to checking for the equality of algorithm (line 78). This can result in an "Object reference not set to an instance of an object." exception thrown. The "object" version of the Equals method (line 97) uses an "obj as PublicKey" cast to this method, which is one example of how null can be passed into the method to start with.
Discovered this error when using an array of public keys in a windows WPF application, the change detection algorithim was enumerating keys to determine if it was necessary to update, a portion of the stack trace follows:
Object reference not set to an instance of an object.
at NSec.Cryptography.PublicKey.Equals(PublicKey other)
at NSec.Cryptography.PublicKey.Equals(Object obj)
at System.Windows.Controls.ItemsControl.EqualsEx(Object o1, Object o2)
at System.Windows.Data.BindingExpression.OnDataContextChanged(DependencyObject contextElement)
As the title mentions, just wondering if there is a plan to introduce X448.
I hate to open an issue as I'm not convinced there's actually an issue with the library. More likely than not I'm using it incorrectly but I can't find documentation to set me on the right path.
I'm attempting to do some code-signing using ed25519. I've made a console app that allows me to create a key and write both the private and public keys to files. Then it moves on and does the code-signing and verification successfully. I can also tell it to read the existing keys from the files, and use them to sign/verify.
My issue is that when I attempt to Import the public key from the file, it fails with the error:
'The key BLOB format 'RawPublicKey' is not supported by the specified algorithm.
I've tried changing the key blob format, and I receive the same error with every one. The file is written, and it reads, correctly.
I've looked at https://github.com/ektrah/nsec/blob/master/src/Cryptography/Ed25519.cs and I see that all 4 of the KeyBlobFormats are supposed to be accepted.
I'd appreciate any direction you can give me on this one.
Here's the code I use to export and then import:
_algorithm = SignatureAlgorithm.Ed25519;
var creationParameters = new KeyCreationParameters
{
ExportPolicy = KeyExportPolicies.AllowPlaintextArchiving
};
_key = new Key(algorithm, creationParameters);
//Export Private Key
var prkBlob = _key.Export(KeyBlobFormat.RawPrivateKey);
File.WriteAllBytes($"{_keyFilename}.prk", prkBlob);
//Export Public Key
var pukBlob = _key.Export(KeyBlobFormat.RawPublicKey);
File.WriteAllBytes($"{_keyFilename}.puk", pukBlob);
//Import Private Key
var prkBlobImport = File.ReadAllBytes($"{_keyFilename}.prk");
Key.TryImport(_algorithm, prkBlobImport, KeyBlobFormat.RawPrivateKey, out _key, in creationParameters);
//Import Public Key
var pukBlobImport = File.ReadAllBytes($"{_keyFilename}.puk");
Key.TryImport(_algorithm, prkBlobImport, KeyBlobFormat.RawPublicKey, out _key, in creationParameters);
After the last line executes, it gives the error I've mentioned above:
'The key BLOB format 'RawPublicKey' is not supported by the specified algorithm.
I'd love to know if I'm using it wrong, or if there's an underlying issue in the library.
Cheers.
Once private key is exported is not secure.
Proposal to add ability to encrypt the private key using a symmetric encryption key derived from a passphrase and then decrypted again.
One of the goals with NSec is to improve on other cryptographic libraries by providing dedicated types for keys (Key
and PublicKey
), nonces (Nonce
), etc. instead of passing everything around as byte arrays.
A quick look around at some GitHub repositories using NSec reveals that API users seem to dislike that entirely. The added safety is quickly defeated by keys being exported right after creation into byte arrays and re-imported for every single encryption/decryption/etc. operation (which is not only error prone but also really slow due to the way keys are stored internally).
Why? ๐
If this feature causes more inconvenience than safety, should it just be removed?
If not, how could API users be encouraged to keep their keys in Key
instances?
I am exploring the library and just wanted to confirm, if I generate a keypair using:
private static Key GenerateKeyPair()
{
var algorithm = SignatureAlgorithm.Ed25519;
// Create a new key pair.
using var key = Key.Create(algorithm, new KeyCreationParameters()
{
ExportPolicy = KeyExportPolicies.AllowPlaintextExport
});
return key;
}
The caller of the method will not be able to export the private key from the returned key object.
The only chance to export the private key is within the above method prior to returning the object?
Is this correct? As when I try to peform the following on the returned key object (as the caller):
var privateKey = key.Export(KeyBlobFormat.KeyBlobFormat.RawPrivateKey);
I am told the object is already disposed.
Dealt with a bug for 3 days because of a single typo of an X25519 key being imported as an Ed25519 key. Would be nice to input a byte[40] and get the key type, if it's valid.
Hello,
I'm wondering if there are any practical differences if I encode "context" into the shared secret vs adding it in the info?
Alt 1:
var passphrase = "my-secret" + username;
var secret = SharedSecret.Import(Encoding.UTF8.GetBytes(passphrase));
var key = KeyDerivationAlgorithm.HkdfSha256.DeriveKey(secret, null, null, MacAlgorithm.HmacSha256)
Alt2
var passphrase = "my-secret";
var info = Encoding.UTF8.GetBytes(username);
var secret = SharedSecret.Import(Encoding.UTF8.GetBytes(passphrase));
var key = KeyDerivationAlgorithm.HkdfSha256.DeriveKey(secret, null, info, MacAlgorithm.HmacSha256)
While using this library, I missed some practical guides. Would you like to receive contributions with "scenario" guides, e.g. "Using NSEC to HMAC your data and then verifying it"?
Thank you for providing this library. It has been quite helpful in trying to get up to speed on cryptography.
I have a specific situation where I have a server that generates a large amount of data over time, and it should encrypt that data for a consumer to decrypt at a later point in time. Using this library, I have worked out (and got a demo working) that we should use a KeyAgreementAlgorithm
and a KeyDerivationAlgorithm
to agree to a shared encryption key (that can be salted).
This does however leave the encrypting party able to decrypt the data after it has been encrypted. I was hoping to avoid that.
I seem to recall that RSA (I may be wrong here) allowed you to encrypt short messages using the other party's public key, and that would come in helpful here. My plan of attack was initially:
At that point (and assuming that you can trust the generator, which is a discussion to be had on its own), only the consumer will be able to decrypt the data, because he is the only one with access to the private key to decrypt the symmetric key.
So the TL;DR: does NSec support (or intend to support) public-key encryption?
Bytes used as an input to the HashAlgorithm are often not in a single span. For that purpose the .NET standard library has the IncrementalHash class. I propose implementing something similar in NSec. Base class would in that case probably look something like this:
public sealed class IncrementalHashAlgorithm : Algorithm, IDisposable
{
public void AppendData(ReadOnlySpan<byte> data);
public bool TryGetHashAndReset(Span<byte> destination, out int bytesWritten);
}
(This is the way IncrementalHash is implemented in .NET Core 2.1, see dotnet/corefx#22614.)
In case that you approve this addition to the API, I would be happy to submit the pull request.
It would be nice to have the ChaCha20 stream cipher exposed for e.g. pseudorandom number generation.
The releases haven't been updated recently and now with XChaCha20-Poly1305 supported by the library, I'd like to use it in my project. Unfortunately I'm unable to do it due to the fact that the nuget is still on version 20.2.0 and hasn't been updated since 2020
https://doc.libsodium.org/advanced/stream_ciphers/xchacha20
Already exists in libsodium, would be nice to not have to worry about nonces.
HKDF.Standard claims to be 2.6 - 6.7 times faster than NSec.
@andreimilto Any quick thoughts on why NSec is so much slower?
Is it the SharedSecret.Import
or the DeriveBytes
call?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.