I am using a python rest server (which I found here: https://github.com/xxblx/tornado-app-template) that supports access tokens and lets a client sign the access tokens. The repository contains a python client that creates a SigningKey on the client side. The provided code shows how to create the required keys and hashes required to create a user that is later able to sign tokens.
# client.py (Line 71 ff)
def signup_user(self):
verify_key = self.signing_key.verify_key
verify_key_hex = verify_key.encode(encoder=nacl.encoding.HexEncoder)
# Encrypt signing key
signing_key_bytes = self.signing_key.encode()
password_hash = nacl.hash.blake2b(self.password.encode(),
encoder=nacl.encoding.HexEncoder)
salt = nacl.utils.random(nacl.pwhash.argon2i.SALTBYTES)
ops = nacl.pwhash.argon2i.OPSLIMIT_SENSITIVE
mem = nacl.pwhash.argon2i.MEMLIMIT_SENSITIVE
key = nacl.pwhash.argon2i.kdf(nacl.secret.SecretBox.KEY_SIZE,
password_hash, salt, opslimit=ops,
memlimit=mem)
box = nacl.secret.SecretBox(key)
nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
encrypted_signing_key = box.encrypt(signing_key_bytes, nonce)
encrypted_signing_key = base64.encodebytes(encrypted_signing_key)
salt = base64.encodebytes(salt)
# Send data to server
data = {
'username': self.username, 'password': self.password,
'privkey': encrypted_signing_key.decode(),
'pubkey_hex': verify_key_hex.decode(),
'privkey_salt': salt.decode(),
'privkey_opslimit': ops, 'privkey_memlimit': mem
}
I want to write a C# client that can generate a SigningKey and is capable of signing the tokens in the same way. I am using libsodium 1.0.16 for my client and I am having trouble creating an equivalent keypair, not to mention finding the corresponding function for creating the password_hash or the key in the above code. I am not even sure which functions to use for the key creation. From my small understanding of crypto, I assume that it should be possible. Any help regarding finding the correct libsodium function for the above used nacl functions (nacl.hash.blake2b, nacl.secret.SecretBox(key), nacl.pwhash.argon2i.kdf(...), etc) or a hint for creating an equivalent SigningKey would be great.
# python SigningKey creation using PyNaCl
_signing_key = nacl.signing.SigningKey.generate()
# --> Line 158 signing.py from nacl
# under the hood SigningKey.generate() uses
public_key, secret_key = nacl.bindings.crypto_sign_seed_keypair(seed)
My approach in C# using libsodium to create this public and secret key looks like this:
pk = new byte[64];
sk = new byte[64];
byte[] seed = unity.libsodium.StreamEncryption.GetRandomBytes(32);
unity.libsodium.NativeLibsodium.crypto_sign_seed_keypair(pk, sk, seed);
Is this a good start?