基于哈希的消息身份验证代码 (MAC) 在接收端不匹配

Hash Based Message Authentication Codes (MAC) does not match at receiver end

我正在尝试创建一个基本的演示应用程序,其中 class 将生成一条以下列格式发送的消息 SignedMessage_using_HMAC.BASE64encoded_message

在接收端 (DecodeData.java) 首先我想比较消息是否使用正确的密钥签名,方法是解密已签名的消息,然后使用相同的密钥对消息签名,然后比较已签名的消息在接收端发送签名消息。 但是这些都不行。

当我尝试解码 Base64 编码的消息时,它没有给我正确的消息。

任何人都可以指导我这里有什么问题吗?

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class EncodeData {

public static void main(String[] args) throws Exception {
    String myAppContext = "abc123def";
    String consumerSecret = "959595";
    String algorithm = "HMACSHA256";
    byte[] encodedContext;

    // Base64 encoded context;
    encodedContext = new Base64(true).encode(myAppContext.getBytes());
    System.out.print("Encoded Context : ");
    System.out.println(encodedContext);

    //Generate Signed context           
    SecretKey hmacKey = new SecretKeySpec(consumerSecret.getBytes(), algorithm);
    Mac mac = Mac.getInstance(algorithm);
    mac.init(hmacKey);

    byte[] digest = mac.doFinal(myAppContext.getBytes());       
    System.out.print("Created digest : ");
    System.out.println(digest);

    // Signed Based64 context and Base64 encoded context        
    String messageToSend = digest.toString() + "." + encodedContext.toString();
    System.out.println(messageToSend);
}   
}

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;

public class DecodeData {

public static void main(String[] args) throws Exception {
    byte[] myAppContext;
    String consumerSecret = "959595";
    String algorithm = "HMACSHA256";
    String messageRecieved = args[0];
    byte[] singedDecodedContext;

    String recievedDigest = messageRecieved.split("[.]", 2)[0];             
    String encodedContext = messageRecieved.split("[.]", 2)[1];
    myAppContext = new Base64(true).decode(encodedContext);
    System.out.print("Decrypted message : ");
    System.out.println(myAppContext);

    //Check if the message is sent by the correct sender by signing the context and matching with signed context
    SecretKey hmacKey = new SecretKeySpec(consumerSecret.getBytes(), algorithm);
    Mac mac = Mac.getInstance(algorithm);
    mac.init(hmacKey);      
    byte[] digest = mac.doFinal(myAppContext);

    System.out.print("Created digest : ");
    System.out.println(digest);

    if (Arrays.equals(digest, recievedDigest.getBytes())) {
        System.out.println("Message was not tempered and was sent by the correct sender");
    } else {
        System.out.println("Message was tempered or was not sent by the corrrect sender");
    }   
}   
}

输出

EncodeData.java的输出 C:\Users\vivek.patel\Desktop\API\java\encoding>java -cp commons-codec-1.10.jar;.编码数据 编码上下文:[B@510bfe2c 创建摘要:[B@73f025cb [B@73f025cb.[B@510bfe2c

DecodeData.java 的输出 C:\Users\vivek.patel\Desktop\API\java\encoding>java -cp commons-codec- 1.10.jar;.解码数据 [B@73f025cb.[B@510bfe2c

Decrypted message : [B@6726a408
Created digest : [B@7168bd8b
Message was tempered or was not sent by the correct sender

在评估您的代码之前,您实际上并没有比较这些值。 如果你这样打印:

System.out.print("Encoded Context : ");
System.out.println(encodedContext);

您只是打印数组的类型 ([B),然后是它的 hashCode。 使用编码字节初始化字符串:

System.out.println(new String(encodedContext, "UTF8"));

您还应该考虑使用显式字符集而不是默认字符集(取决于您的原始字符集)。

试一试并重新post你的结果。