AWS Lambda not generating same HMAC as client (NET CORE 2.1)

0

I used the below code to generate a HMAC (signed hash) token on a client and again within a Lambda function to validate.

On my client app (.NET Core 2.1), it works fine. It both generates a HMAC token and it validates perfectly.

Put the same code in a Lambda and an issue arises. When the generated string is set to a Lambda endpoint, it always validates false. I even sent the string back to the client and once again, it validated fine.

Its almost as if there were a bug in the Lambda implementation of Net Core.

private static string GenerateHMAC(string password, string challenge)
{
HMACSHA256 hmc = new HMACSHA256(Encoding.UTF8.GetBytes(password));
byte[] hmres = hmc.ComputeHash(Encoding.UTF8.GetBytes(challenge));
string hmac = ByteToString(hmres);//
Console.WriteLine(hmac);
return hmac;
}

    private static bool ValidateHMAC(string password, string challenge, string suppliedHMAC)  
    {  
        HMACSHA256 hmc = new HMACSHA256(Encoding.UTF8.GetBytes(password));  
        byte\[] hmres = hmc.ComputeHash(Encoding.UTF8.GetBytes(challenge));  
        string hmac = ByteToString(hmres);//  
        Console.WriteLine(hmac);  

        if (suppliedHMAC == hmac)  
            return true;  
        else  
            return false;  
    }  

    public static string ByteToString(byte\[] buff)  
    {  
        string sbinary = "";  

        for (int i = 0; i < buff.Length; i++)  
        {  
            sbinary += buff\[i].ToString("X2"); // hex format  
        }  
        return (sbinary);  
    }
mmcc
gefragt vor 5 Jahren438 Aufrufe
4 Antworten
0

I'm not able to reproduce any problem. I took your code and wrapped into a Lambda function like this and it returns true. Is there any more information you can give to help reproduce your issue.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace LambdaHmacTest
{
    public class Function
    {
        
        public bool FunctionHandler(ILambdaContext context)
        {
            var password = "foobar";
            var challenge = "this is a test";

            var hmac = GenerateHMAC(password, challenge);
            context.Logger.LogLine($"Password: {password}, Challenge: {challenge}, Hmac: {hmac}");
            var validate = ValidateHMAC(password, challenge, hmac);
            context.Logger.LogLine($"IsValid: {validate}");


            return validate;
        }

        private static string GenerateHMAC(string password, string challenge)
        {
            HMACSHA256 hmc = new HMACSHA256(Encoding.UTF8.GetBytes(password));
            byte[] hmres = hmc.ComputeHash(Encoding.UTF8.GetBytes(challenge));
            string hmac = ByteToString(hmres);//
            Console.WriteLine(hmac);
            return hmac;
        }

        private static bool ValidateHMAC(string password, string challenge, string suppliedHMAC)
        {
            HMACSHA256 hmc = new HMACSHA256(Encoding.UTF8.GetBytes(password));
            byte[] hmres = hmc.ComputeHash(Encoding.UTF8.GetBytes(challenge));
            string hmac = ByteToString(hmres);//
            Console.WriteLine(hmac);

            if (suppliedHMAC == hmac)
                return true;
            else
                return false;
        }

        public static string ByteToString(byte[] buff)
        {
            string sbinary = "";

            for (int i = 0; i < buff.Length; i++)
            {
                sbinary += buff[i].ToString("X2"); // hex format
            }
            return (sbinary);
        }
    }
}
AWS
Norm
beantwortet vor 5 Jahren
0

Generate the HMAC on a client, pass the string to the Lambda endpoint (UTF8), then try to recreate the HMAC. I am getting different bytes, hence a different HMAC.

mmcc
beantwortet vor 5 Jahren
0

This is the code I use to generate the token client side. When the HMAC is validated in the Lambda, it will fail. If I do it locally, it works fine.

private static bool TestUnit()
        {
            
            Console.WriteLine("Beginning test of endpoint ");
            string url = "replace with endpoint url";

            MyRequest mr = new MyRequest();
            cr.Role = Roles.Unit;  //0 indexed enum
            cr.Timestamp = DateTime.UtcNow;
            cr.UnitId = Guid.NewGuid();
            cr.HMAC = GenerateHMAC(hmacSecret, cr.UnitId.ToString() + cr.Timestamp.ToString() + (int)cr.Role);

            HttpClient client = new HttpClient();
            //client.DefaultRequestHeaders.Add("x-api-key", "add api key");

            string jsonObject = JsonConvert.SerializeObject(cr);
            var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");

            try
            {
                var result = client.PostAsync(url, content).Result;
                Console.WriteLine(result);
                Console.WriteLine(result.Content.ReadAsStringAsync().Result);

                Console.WriteLine();
                Console.WriteLine("Ending test of endpoint Create");
                return true;
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
        }
		
		
[Serializable]
    public enum Roles
    {
        Unit = 0,
        SmallUnit,
        BigUnit,
    }

    public class MyRequest
    {
        public string HMAC { get; set; }
        public Roles Role { get; set; }
        public Guid UnitId { get; set; }
        public DateTime Timestamp { get; set; }
    }
mmcc
beantwortet vor 5 Jahren
0

I think I found the issue. The DateTime format is different between the client and server. Defining a format resolves the issue.

string format = "MMM ddd d HH:mm yyyy";

This can be passed as a variable to the .ToString(format) method of DateTime object.

mmcc
beantwortet vor 5 Jahren

Du bist nicht angemeldet. Anmelden um eine Antwort zu veröffentlichen.

Eine gute Antwort beantwortet die Frage klar, gibt konstruktives Feedback und fördert die berufliche Weiterentwicklung des Fragenstellers.

Richtlinien für die Beantwortung von Fragen