基于哈希的消息认证码(MAC)在接收端不匹配

时间:2015-04-01 06:45:25

标签: java encryption hmac

我正在尝试创建一个基本的演示应用程序,其中一个类将生成以下列格式发送的消息 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;。 EncodeData     编码上下文:[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;。 DecodeData [B @ 73f025cb。[B @ 510bfe2c

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

1 个答案:

答案 0 :(得分:0)

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

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

您只是打印数组的类型([B]后跟其hashCode。 使用编码的字节初始化String:

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

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

尝试并重新发布结果。