public async ValueTask <string> CreateNodeTokenAsync(CancellationToken cancellationToken) { // An IV (initialization vector) is used to make sure that if we encode the same text over // and over again, the resulting value will never be the same. This is good for security, // because if tokens leak, then the attacker cannot determine to which server traffic is // routed (or if it's the same server). Another advantage of this uniqueness is that the // bride token is nog also unique and can be used to differentiate between different bridges using var aes = Aes.Create(); aes.Key = await _encryptionKeyProvider.GetKeyAsync(cancellationToken).ConfigureAwait(false); var encryptor = aes.CreateEncryptor(aes.Key, aes.IV); var encryptedBytes = encryptor.TransformFinalBlock(_urlBytes, 0, _urlBytes.Length); var bytes = new byte[aes.IV.Length + encryptedBytes.Length]; Buffer.BlockCopy(aes.IV, 0, bytes, 0, aes.IV.Length); Buffer.BlockCopy(encryptedBytes, 0, bytes, aes.IV.Length, encryptedBytes.Length); return(bytes.ToUrlSafeBase64()); }
public async Task <string> SignAsync(object obj, CancellationToken cancellationToken = default) { var key = await _encryptionKeyProvider.GetKeyAsync(cancellationToken).ConfigureAwait(false); using var hmac = new HMACSHA256(key); var json = JsonSerializer.Serialize(obj, obj.GetType()); var jsonBytes = Encoding.UTF8.GetBytes(json); var hash = hmac.ComputeHash(jsonBytes); return(hash.ToUrlSafeBase64()); }