Code Monkey home page Code Monkey logo

nsec's Introduction

NSec

Maintenance License NuGet

NSec is a cryptographic library for .NET 8+ based on libsodium โค. It provides modern cryptographic primitives in a modern API based on Span<T>. NSec aims to be easy to use, secure by default, fast, and agile.

For more information about NSec, please refer to the following resources:

Project homepage: https://nsec.rocks/
Installation: https://nsec.rocks/docs/install
Online documentation: https://nsec.rocks/docs/api/nsec.cryptography
Open issues: https://github.com/ektrah/nsec/issues
Pull requests: https://github.com/ektrah/nsec/pulls

nsec's People

Contributors

ektrah avatar enclave-alistair avatar irubens avatar joemphilips avatar nickstrupat avatar p3root avatar sigaloid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nsec's Issues

Merge pull request 32 into NSec.Experimental (ed25519 to x25519 conversion)

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. ๐Ÿคทโ€โ™‚๏ธ

'The key BLOB format 'RawPublicKey' is not supported by the specified algorithm.

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.

Plans for argon2

Hello good day is there any plans for supporting Argon2 password hashing?

Private Key

Once the key generated, how do I get private key to store it?!

NSec and Unity 3D

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.

Full .NET framework build?

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,

Update releases and nuget

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

ref struct `PublicKey`?

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?

Struggling to compile the solution

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.

Proposal: IncrementalHashAlgorithm

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.

System.ArgumentException: 'The specified key is for algorithm 'NSec.Cryptography.ChaCha20Poly1305'. Expected 'NSec.Cryptography.ChaCha20Poly1305'.

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.

Why do API users prefer byte arrays to Key instances?

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?

The key BLOB format 'RawPublicKey' is not supported by the specified algorithm ChaCha20Poly1305

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
                    });
    }

How to export and save sharedsecret key

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.

Add support for multiple minor versions of libsodium?

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.

How to choose KeyBlobFormat?

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.

Clarify security issues when using random nonces

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?

Making use of the library if having the private key pre-generated as a byte array?

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?

What it means in practice: "Using the same nonce with the same key more than once leads to catastrophic loss of security."

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! ๐Ÿ˜

PublickKey Equals method can throw "Object reference not set to an instance of an object."

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)

Assistance with accessing Private Key.

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.

KDF: Difference between adding context in sharedsecret vs info?

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"?

.NET Standard < 2.0

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.

https://github.com/dotnet/core/blob/master/roadmap.md

NSEC on Xamarim Forms - Platform Not Supported

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 "

Add support for passing seed in key creation

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 :
image

Regards,
Rinkal Bhojani

Having trouble encrypting through stdin/out

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?

Are PasswordHash methods supported?

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
}

How to generate the same shared secret through different keypairs?

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?

Document usage regarding DLLs

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

Support for more algorithms in libsodium

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.

"Classic" public key encryption?

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:

  1. The generator creates a random (or at least non-derivable at a later stage) symmetric key.
  2. The generator encrypts the symmetric key using the consumer's public key.
  3. The generator encrypts the data using the symmetric key.
  4. The generator publishes both values.

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.