示例#1
0
        /// <summary>
        ///     Validate a file with a MinisignSignature and a MinisignPublicKey object.
        /// </summary>
        /// <param name="filePath">The full path to the file.</param>
        /// <param name="signature">A valid MinisignSignature object.</param>
        /// <param name="publicKey">A valid MinisignPublicKey object.</param>
        /// <returns><c>true</c> if valid; otherwise, <c>false</c>.</returns>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static bool ValidateSignature(string filePath, MinisignSignature signature, MinisignPublicKey publicKey)
        {
            if (filePath != null && !File.Exists(filePath))
            {
                throw new FileNotFoundException("could not find filePath");
            }

            if (signature == null)
            {
                throw new ArgumentException("missing signature input", nameof(signature));
            }

            if (publicKey == null)
            {
                throw new ArgumentException("missing publicKey input", nameof(publicKey));
            }

            if (!ArrayHelpers.ConstantTimeEquals(signature.KeyId, publicKey.KeyId))
            {
                return(false);
            }
            // load the file into memory
            var file = LoadMessageFile(filePath);

            // verify the signature
            if (PublicKeyAuth.VerifyDetached(signature.Signature, file, publicKey.PublicKey))
            {
                // verify the trusted comment
                return(PublicKeyAuth.VerifyDetached(signature.GlobalSignature,
                                                    ArrayHelpers.ConcatArrays(signature.Signature, signature.TrustedComment), publicKey.PublicKey));
            }

            return(false);
        }
        /// <summary>
        ///   Validates server acceptance message
        /// </summary>
        /// <remark>
        ///   Here the client verifies that the received message length is 80
        ///   bytes, then opens the encrypted box and verifies that the sent
        ///   message is server's signature to the derived shared secrets. With
        ///   this the handshake concludes.
        /// </remark>
        /// <exception cref="ArgumentException">
        ///   Thrown if the server's Accept <paramref name="msg"/> is not the
        ///   correct size or the signature is not valid.
        /// </exception>
        /// <param name="msg">
        ///   The received message, encrypted server's signature.
        /// </param>
        public void VerifyAccept(byte[] msg)
        {
            if (msg.Length != 80)
            {
                throw new ArgumentException("Incorrect message size");
            }

            var nonce = new byte[NONCE_SIZE];

            nonce.Initialize();

            // Concatenate the network key and derived secrets to obtain
            // the message key
            var key = CryptoHash.Sha256(
                Utils.Concat(_network_key, _shared_ab, _shared_aB, _shared_Ab)
                );

            var opened_msg = SecretBox.Open(msg, nonce, key);

            // Compute the message that it is supposed to be signed with the
            // server's long term key
            var hashed        = CryptoHash.Sha256(_shared_ab);
            var msg_to_verify = Utils.Concat(
                _network_key, detached_signature_A,
                _longterm_client_keypair.PublicKey, hashed
                );

            if (!PublicKeyAuth.VerifyDetached(opened_msg, msg_to_verify, _longterm_server_pk))
            {
                throw new ArgumentException("Invalid signature");
            }
        }
示例#3
0
        /// <summary>
        ///     Validate a file with a MinisignSignature and a MinisignPublicKey object.
        /// </summary>
        /// <param name="message">The message to validate.</param>
        /// <param name="signature">A valid MinisignSignature object.</param>
        /// <param name="publicKey">A valid MinisignPublicKey object.</param>
        /// <returns><c>true</c> if valid; otherwise, <c>false</c>.</returns>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static bool ValidateSignature(byte[] message, MinisignSignature signature, MinisignPublicKey publicKey)
        {
            if (message == null)
            {
                throw new ArgumentException("missing signature input", nameof(message));
            }

            if (signature == null)
            {
                throw new ArgumentException("missing signature input", nameof(signature));
            }

            if (publicKey == null)
            {
                throw new ArgumentException("missing publicKey input", nameof(publicKey));
            }

            if (!ArrayHelpers.ConstantTimeEquals(signature.KeyId, publicKey.KeyId))
            {
                return(false);
            }
            // verify the signature
            if (PublicKeyAuth.VerifyDetached(signature.Signature, message, publicKey.PublicKey))
            {
                // verify the trusted comment
                return(PublicKeyAuth.VerifyDetached(signature.GlobalSignature,
                                                    ArrayHelpers.ConcatArrays(signature.Signature, signature.TrustedComment), publicKey.PublicKey));
            }

            return(false);
        }
示例#4
0
        public bool isValidSignature(Interaction interaction)
        {
            var signature = Context.Request.Headers["X-Signature-Ed25519"];

            signature ??= Context.Request.Headers["X-Signature-Ed25519".ToLower()];
            var timestamp = Context.Request.Headers["X-Signature-Timestamp"];

            timestamp ??= Context.Request.Headers["X-Signature-Timestamp".ToLower()];
            Program.LogMsg($"Verifying {timestamp} with {signature}");
            var message   = timestamp + Context.Body;
            var publicKey = Program.Configuration["tokens:publickey"];

#if !DEBUG
            if (!PublicKeyAuth.VerifyDetached(
                    Sodium.Utilities.HexToBinary(signature),
                    Encoding.UTF8.GetBytes(message),
                    Sodium.Utilities.HexToBinary(publicKey)))
            {
                Program.LogMsg($"Failed verification.");
                return(false);
            }
#endif
            Program.LogMsg($"Suceeded verification");
            return(true);
        }
示例#5
0
 public void VerifyAuthDetachedBadSignature()
 {
     PublicKeyAuth.VerifyDetached(
         Utilities.HexToBinary("5436accbe258a6b252c1140f38d7b8dc6196619945818b72512b6a8019d86dfeeb56f40c4d4b983d97dfeed37948527256c3567d6b253757fcfb32bef56f0b"),
         Encoding.UTF8.GetBytes("Adam Caudill"),
         Utilities.HexToBinary("4ffda13c11d61d2b9568e54bec06ea59368e84874883087645e64e5e9653422e"));
 }
        public void VerifyAuthDetachedBadSignature()
        {
            var signature = Utilities.HexToBinary("5436accbe258a6b252c1140f38d7b8dc6196619945818b72512b6a8019d86dfeeb56f40c4d4b983d97dfeed37948527256c3567d6b253757fcfb32bef56f0b");
            var message   = Encoding.UTF8.GetBytes("Adam Caudill");
            var key       = Utilities.HexToBinary("4ffda13c11d61d2b9568e54bec06ea59368e84874883087645e64e5e9653422e");

            Assert.Throws <SignatureOutOfRangeException>(
                () => PublicKeyAuth.VerifyDetached(signature, message, key));
        }
示例#7
0
        public void GenerateKeyVerifySignedDataTest()
        {
            var actual = PublicKeyAuth.GenerateKeyPair();

            byte[] randomArray = SodiumCore.GetRandomBytes(255);
            var    sign        = PublicKeyAuth.SignDetached(randomArray, actual.PrivateKey);

            Assert.IsTrue(PublicKeyAuth.VerifyDetached(sign, randomArray, actual.PublicKey));
        }
示例#8
0
        /// <summary>
        /// Create callback function for public key verification
        /// </summary>
        /// <remarks>
        /// PublicKeyVerifier sometimes required
        /// for peers that are receiving a static public key at some
        /// point during the handshake
        /// </remarks>
        /// <param name="rootPublicKey"></param>
        /// <returns>Callback delegate</returns>
        public static Config.PublicKeyVerifierDeligate CreatePublicKeyVerifier(byte[] rootPublicKey)
        {
            return((publicKey, proof) =>
            {
                if (publicKey.Length != Asymmetric.DhLen)
                {
                    return false;
                }

                return PublicKeyAuth.VerifyDetached(proof, publicKey, rootPublicKey);
            });
        }
示例#9
0
        /// <summary>
        ///   Checks for <paramref name="msg"/> length and validity, extracting
        ///   the client's long term public key upon success.
        /// </summary>
        /// <param name="msg">Client authenticate message</param>
        /// <exception cref="ArgumentException">
        ///   Thrown if the client Auth <paramref name="msg"/> fails to pass the
        ///   checks.
        /// </exception>
        public void AcceptAuth(byte[] msg)
        {
            if (msg.Length != 112)
            {
                throw new ArgumentException("Incorrect secretbox length");
            }

            // A nonce consisting of 24 zeros
            var nonce = new byte[NONCE_SIZE];

            nonce.Initialize();

            // Calculate the decryption key from the dervided keys
            var key = CryptoHash.Sha256(
                Utils.Concat(_network_key, _shared_ab, _shared_aB)
                );

            var opened_msg = SecretBox.Open(msg, nonce, key);

            if (opened_msg.Length != 96)
            {
                throw new ArgumentException("Invalid size of opened message");
            }

            // Extract the signature of the long term client's public key
            // signed with the derived secret
            var detached_signature = new byte[SIG_SIZE];

            Buffer.BlockCopy(opened_msg, 0, detached_signature, 0, SIG_SIZE);

            // Extract the long term client's public key
            var lt_cli_pk = new byte[PUB_KEY_SIZE];

            Buffer.BlockCopy(opened_msg, SIG_SIZE, lt_cli_pk, 0, PUB_KEY_SIZE);

            var shared_hashed = CryptoHash.Sha256(_shared_ab);
            // Concat network_key, server longterm pk and sha256 hashed shared_ab secret
            var to_verify = Utils.Concat(
                _network_key, _longterm_server_keypair.PublicKey, shared_hashed
                );

            if (!PublicKeyAuth.VerifyDetached(detached_signature, to_verify, lt_cli_pk))
            {
                throw new ArgumentException("Signature does not match");
            }

            detached_signature_A = detached_signature;
            _longterm_client_pk  = lt_cli_pk;
            this.DeriveAb();
        }
示例#10
0
        public void VerifyAuthDetachedBadKey()
        {
            //Don`t copy bobSk for other tests (bad key)!
            //30 byte
            var bobSk = new byte[] {
                0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b,
                0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6,
                0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd,
                0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88
            };

            PublicKeyAuth.VerifyDetached(
                Utilities.HexToBinary("8d5436accbe258a6b252c1140f38d7b8dc6196619945818b72512b6a8019d86dfeeb56f40c4d4b983d97dfeed37948527256c3567d6b253757fcfb32bef56f0b"),
                Encoding.UTF8.GetBytes("Adam Caudill"),
                bobSk);
        }
示例#11
0
        /// <summary>
        /// Returns true if the signature associated with a given message is valid
        /// </summary>
        /// <param name="response">Decrypted string representation of the response</param>
        /// <param name="signature">64 byte signature</param>
        /// <param name="publicKey">32 byte public key</param>
        /// <returns>`true` if the signature is valid, and false otherwise</returns>
        public bool IsSignatureValid(String response, byte[] signature, byte[] publicKey)
        {
            if (signature.Length != 64)
            {
                throw new ArgumentException(String.Format("Signature should be %d bytes.", 64));
            }

            if (publicKey.Length != 32)
            {
                throw new ArgumentException(String.Format("Public key should be %d bytes.", 64));
            }

            try {
                return(PublicKeyAuth.VerifyDetached(
                           signature,
                           System.Text.Encoding.UTF8.GetBytes(response),
                           publicKey
                           ));
            } catch (Exception e) {
                throw new SignatureVerificationException("Unable to calculate signature.", e);
            }
        }
示例#12
0
        public static bool VerifySignature(string signatureFilePath, string filePath, byte[] publicKey)
        {
            using var signatureFile = new FileStream(signatureFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.RandomAccess);
            // Verify the global signature
            byte[] magicBytes    = GetMagicBytes(signatureFile);
            byte[] formatVersion = GetFormatVersion(signatureFile);
            FileHeaders.ValidateFormatVersion(signatureFilePath, formatVersion, Constants.SignatureVersion);
            byte[] preHashedHeader = GetPreHashedHeader(signatureFile);
            byte[] fileSignature   = GetFileSignature(signatureFile);
            _commentBytes = GetCommentBytes(signatureFile);
            byte[] signatureFileBytes   = Utilities.ConcatArrays(magicBytes, formatVersion, preHashedHeader, fileSignature, _commentBytes);
            bool   validGlobalSignature = VerifyGlobalSignature(signatureFile, signatureFileBytes, publicKey);

            if (!validGlobalSignature)
            {
                return(false);
            }
            // Verify the file signature
            bool preHashed = BitConverter.ToBoolean(preHashedHeader);

            byte[] fileBytes = GetFileBytes(filePath, preHashed);
            return(PublicKeyAuth.VerifyDetached(fileSignature, fileBytes, publicKey));
        }
示例#13
0
        public static bool VerifySignature(string signatureFilePath, string filePath, byte[] publicKey, out string comment)
        {
            using var signatureFile = new FileStream(signatureFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.SequentialScan);
            byte[] magicBytes    = GetMagicBytes(signatureFile);
            byte[] formatVersion = GetFormatVersion(signatureFile);
            FileHeaders.ValidateFormatVersion(formatVersion, Constants.SignatureVersion);
            byte[] preHashed            = GetPreHashedHeader(signatureFile);
            byte[] fileSignature        = GetFileSignature(signatureFile);
            byte[] commentBytes         = GetCommentBytes(signatureFile);
            byte[] signatureFileBytes   = Arrays.Concat(magicBytes, formatVersion, preHashed, fileSignature, commentBytes);
            bool   validGlobalSignature = VerifyGlobalSignature(signatureFile, signatureFileBytes, publicKey);

            if (!validGlobalSignature)
            {
                comment = string.Empty;
                return(false);
            }
            bool preHash = BitConverter.ToBoolean(preHashed);

            byte[] fileBytes = GetFileBytes(filePath, preHash);
            comment = Encoding.UTF8.GetString(commentBytes);
            return(PublicKeyAuth.VerifyDetached(fileSignature, fileBytes, publicKey));
        }
        public void DetachedSignTest()
        {
            var    kp      = PublicKeyAuth.GenerateKeyPair();
            string message = "Hello, World!";

            byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message);

            var sig1 = PublicKeyAuth.SignDetached(message, kp.Secret);
            var sig2 = PublicKeyAuth.SignDetached(byteMessage, kp.Secret);

            Assert.AreEqual(Convert.ToBase64String(sig1), Convert.ToBase64String(sig2));
            Assert.AreEqual(64, sig1.Length);
            Assert.AreEqual(64, sig2.Length);

            Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig1, byteMessage, kp.Public));
            Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig1, message, kp.Public));
            Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig2, byteMessage, kp.Public));
            Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig2, message, kp.Public));

            var kp2 = PublicKeyAuth.GenerateKeyPair();

            Assert.IsFalse(PublicKeyAuth.VerifyDetached(sig2, message, kp2.Public));
            Assert.IsFalse(PublicKeyAuth.VerifyDetached(sig2, "Invalid message test", kp.Public));
        }
示例#15
0
 public static bool Verify(byte[] signature, byte[] payload, byte[] publicKey) =>
 PublicKeyAuth.VerifyDetached(signature, payload, publicKey);
示例#16
0
 public static bool ValidateSQRLPost(byte[] sig, string client, string server, byte[] key)
 {
     return(PublicKeyAuth.VerifyDetached(sig, (client + server).UTF8Bytes(), key));
 }
示例#17
0
 static bool LibsodiumVerifyDetachedFromBase64(byte[] publicKey, string dataToSign, string signatureBase64)
 {
     byte[] data      = System.Text.Encoding.UTF8.GetBytes(dataToSign);
     byte[] signature = Base64Decoding(signatureBase64);
     return(PublicKeyAuth.VerifyDetached(signature, data, publicKey));
 }
示例#18
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (_settings.Value.PublicKey == null)
            {
                return;
            }

            // Do something before the action executes.
            var request = context.HttpContext.Request;

            try
            {
                // Get the verification headers from the request ...
                var signature = request.Headers["X-Signature-Ed25519"].ToString();
                var timestamp = request.Headers["X-Signature-Timestamp"].ToString();
                // ... convert the signature and public key to byte[] to use in verification ...
                var byteSig = HexConverter.HexStringToByteArray(signature);
                // NOTE: This reads your Public Key that you need to store somewhere.
                var byteKey = HexConverter.HexStringToByteArray(_settings.Value.PublicKey);
                // ... read the body from the request ...

                if (byteSig.Length < 1 || byteKey.Length < 1)
                {
                    _logger.LogWarning("Failed to validate POST request for Discord API.");
                    context.Result = new UnauthorizedResult();
                    return;
                }


                var raw = request.BodyToString();

                /*
                 * using var reader = new StreamReader(request.Body);
                 * if (reader.BaseStream.CanSeek)
                 *  reader.BaseStream.Seek(0, SeekOrigin.Begin);
                 * string raw = reader.ReadToEndAsync().Result;
                 *
                 * reader.Dispose();
                 */

                // ... add the timestamp and convert it to a byte[] ...
                string body     = timestamp + raw;
                var    byteBody = Encoding.Default.GetBytes(body);
                // ... run through a verification with all the byte[]s ...
                bool validated = PublicKeyAuth.VerifyDetached(byteSig, byteBody, byteKey);
                // ... if it is not validated ...
                if (!validated)
                {                                              // ... log a warning and return a 401 Unauthorized.
                    _logger.LogWarning("Failed to validate POST request for Discord API.");
                    context.Result = new UnauthorizedResult(); // Unauthorized("Invalid Request Signature");
                    return;
                }
                else
                { // ... otherwise continue onwards.
                    _logger.LogInformation("Received POST from Discord");
                }
            }
            catch (Exception ex)
            { // ... if an error occurred, log the error and return at 401 Unauthorized.
                _logger.LogInformation(ex, "Decryption failed.");
                _logger.LogWarning("Failed to validate POST request for Discord API.");
                context.Result = new UnauthorizedResult();// Unauthorized("Invalid Request Signature");
                return;
            }
            finally
            {
                //context.HttpContext.Request = request;
            }

            //request.Body.Position = 0;
        }
示例#19
0
 private static bool VerifyGlobalSignature(FileStream signatureFile, byte[] signatureFileBytes, byte[] publicKey)
 {
     byte[] globalSignature = GetGlobalSignature(signatureFile);
     return(PublicKeyAuth.VerifyDetached(globalSignature, signatureFileBytes, publicKey));
 }
示例#20
0
 public static bool Verify(byte[] sign, byte[] msg, byte[] publicKey)
 {
     return(PublicKeyAuth.VerifyDetached(sign, msg, publicKey));
 }
 public override bool Verify(byte[] input, byte[] signature)
 => PublicKeyAuth.VerifyDetached(signature, input, ((SodiumSecurityKey)Key).PublicKey);
示例#22
0
        //[ApiExplorerSettings(IgnoreApi = true)]
        public async Task <IActionResult> DiscordEndpointHandler()
        {
            string raw;

            // Request validation
            try
            {
                // Get the verification headers from the request ...
                var signature = Request.Headers["X-Signature-Ed25519"].ToString();
                var timestamp = Request.Headers["X-Signature-Timestamp"].ToString();
                // ... convert the signature and public key to byte[] to use in verification ...
                var byteSig = Utils.HexStringToByteArray(signature);
                var byteKey = Utils.HexStringToByteArray(Startup.PublicKey);
                // ... read the body from the request ...
                using var reader = new StreamReader(Request.Body);
                if (reader.BaseStream.CanSeek)
                {
                    reader.BaseStream.Seek(0, SeekOrigin.Begin);
                }
                raw = await reader.ReadToEndAsync();

                // ... add the timestamp and convert it to a byte[] ...
                string body     = timestamp + raw;
                var    byteBody = Encoding.Default.GetBytes(body);
                // ... run through a verification with all the byte[]s ...
                bool validated = PublicKeyAuth.VerifyDetached(byteSig, byteBody, byteKey);
                // ... if it is not validated ...
                if (!validated)
                {   // ... log a warning and return a 401 Unauthorized.
                    _logger.LogWarning("Failed to validate POST request for Discord API.");
                    return(Unauthorized("Invalid Request Signature"));
                }
                else
                { // ... otherwise continue onwards.
                    _logger.LogInformation("Received POST from Discord");
                }
            }
            catch (Exception ex)
            { // ... if an error occurred, log the error and return at 401 Unauthorized.
                _logger.LogInformation(ex, "Decryption failed.");
                _logger.LogWarning("Failed to validate POST request for Discord API.");
                return(Unauthorized("Invalid Request Signature"));
            }

            // Response parsing
            JObject json;

            try
            { // ... attempt to create a json object from the body ...
                json = JObject.Parse(raw);
            }
            catch
            { // ... if that fails, return a 400 Bad Request.
                return(BadRequest());
            }
            // ... check to see if this is a ping to the webhook ...
            if (json.ContainsKey("type") && (int)json["type"] == (int)InteractionType.Ping)
            {
                return(Ok(
                           JsonConvert.SerializeObject(
                               new InteractionResponseBuilder()
                               .WithType(InteractionResponseType.Pong)
                               .Build()
                               )
                           )); // ... and return the pong if it is.
            }
            else
            {// ... then pass the raw request body to the client ...
                var response = await Program.Slash.HandleWebhookPost(raw);

                if (response is not null)                              // ... if the clients response is not null ...
                {
                    return(Ok(JsonConvert.SerializeObject(response))); // ... serialize it and send it.
                }
                else
                {
                    return(BadRequest("Failed to parse request JSON.")); // ... or send a bad request message.
                }
            }
        }
 /// <summary>
 /// Verifiies the message.
 /// </summary>
 /// <returns><c>true</c>, if sign was verifiyed, <c>false</c> otherwise.</returns>
 /// <param name="signature">Signature.</param>
 /// <param name="message">Message.</param>
 /// <param name="pk">Pk.</param>
 public static bool VerifiySign(byte[] signature, byte[] message, byte[] pk) => PublicKeyAuth.VerifyDetached(signature, message, pk);
示例#24
0
 public static bool VerifySignature(byte[] publicKey, byte[] signature, byte[] message)
 {
     return(PublicKeyAuth.VerifyDetached(signature, message, publicKey));
 }