// Path: src/main/java/net/seleucus/wsp/crypto/fwknop/fields/DigestType.java
// public enum DigestType {
// 
//     MD5(1, "MD5"),
//     SHA1(2, "SHA-1"),
//     SHA256(3, "SHA-256"),
//     SHA384(4, "SHA-384"),
//     SHA512(5, "SHA-512");
// 
//     private final int id;
//     private final String algorithmName;
// 
//     private DigestType(final int id, final String algorithmName) {
//         this.id = id;
//         this.algorithmName = algorithmName;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public String algorithmName() {
//         return algorithmName;
//     }
// }
// 
// Path: src/main/java/net/seleucus/wsp/crypto/fwknop/fields/MessageType.java
// public enum MessageType {
// 
//     CommandMessage(0),
//     AccessMessage(1),
//     NatAccessMessage(2),
//     ClientTimeOutAccessMessage(3),
//     ClientTimeOutNatAccessMessage(4),
//     LocalNatAccessMessage(5),
//     ClientTimeoutLocalNatAccessMessage(6);
// 
//     private int id;
// 
//     private MessageType(int id) {
//         this.id = id;
//     }
// 
//     public int getId() {
//         return id;
//     }
// }
// 
// Path: src/main/java/net/seleucus/wsp/crypto/fwknop/FwknopBase64.java
// public static String encode(byte[] input){
//     return StringUtils.remove(Base64.encodeBase64String(input), CHAR_TO_REMOVE);
// }


import net.seleucus.wsp.crypto.fwknop.fields.DigestType;
import net.seleucus.wsp.crypto.fwknop.fields.MessageType;
import org.apache.commons.codec.binary.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import static java.util.Objects.requireNonNull;
import static net.seleucus.wsp.crypto.fwknop.FwknopBase64.encode;
import static org.apache.commons.codec.Charsets.UTF_8;
package net.seleucus.wsp.crypto.fwknop;




public class Message {

    public static final char FIELD_DELIMITER = ':';

    private final long randomValue;
    private final String username;
    private final long timestamp;
    private final String version;
    private final MessageType messageType;
    private final String payload;
    private final DigestType digestType;

    Message(long randomValue, String username, long timestamp, String version, MessageType messageType, String payload, DigestType digestType) {
        this.digestType = digestType;
        this.randomValue = requireNonNull(randomValue);
        this.username = requireNonNull(username);
        this.timestamp = requireNonNull(timestamp);
        this.version = requireNonNull(version);
        this.messageType = requireNonNull(messageType);
        this.payload = requireNonNull(payload);
    }

    public String encoded(){
        return new StringBuilder()
            .append(randomValue).append(FIELD_DELIMITER)
// Path: src/main/java/net/seleucus/wsp/crypto/fwknop/fields/DigestType.java
// public enum DigestType {
// 
//     MD5(1, "MD5"),
//     SHA1(2, "SHA-1"),
//     SHA256(3, "SHA-256"),
//     SHA384(4, "SHA-384"),
//     SHA512(5, "SHA-512");
// 
//     private final int id;
//     private final String algorithmName;
// 
//     private DigestType(final int id, final String algorithmName) {
//         this.id = id;
//         this.algorithmName = algorithmName;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public String algorithmName() {
//         return algorithmName;
//     }
// }
// 
// Path: src/main/java/net/seleucus/wsp/crypto/fwknop/fields/MessageType.java
// public enum MessageType {
// 
//     CommandMessage(0),
//     AccessMessage(1),
//     NatAccessMessage(2),
//     ClientTimeOutAccessMessage(3),
//     ClientTimeOutNatAccessMessage(4),
//     LocalNatAccessMessage(5),
//     ClientTimeoutLocalNatAccessMessage(6);
// 
//     private int id;
// 
//     private MessageType(int id) {
//         this.id = id;
//     }
// 
//     public int getId() {
//         return id;
//     }
// }
// 
// Path: src/main/java/net/seleucus/wsp/crypto/fwknop/FwknopBase64.java
// public static String encode(byte[] input){
//     return StringUtils.remove(Base64.encodeBase64String(input), CHAR_TO_REMOVE);
// }


// Path: src/main/java/net/seleucus/wsp/crypto/fwknop/Message.java
import net.seleucus.wsp.crypto.fwknop.fields.DigestType;
import net.seleucus.wsp.crypto.fwknop.fields.MessageType;
import org.apache.commons.codec.binary.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import static java.util.Objects.requireNonNull;
import static net.seleucus.wsp.crypto.fwknop.FwknopBase64.encode;
import static org.apache.commons.codec.Charsets.UTF_8;

package net.seleucus.wsp.crypto.fwknop;




public class Message {

    public static final char FIELD_DELIMITER = ':';

    private final long randomValue;
    private final String username;
    private final long timestamp;
    private final String version;
    private final MessageType messageType;
    private final String payload;
    private final DigestType digestType;

    Message(long randomValue, String username, long timestamp, String version, MessageType messageType, String payload, DigestType digestType) {
        this.digestType = digestType;
        this.randomValue = requireNonNull(randomValue);
        this.username = requireNonNull(username);
        this.timestamp = requireNonNull(timestamp);
        this.version = requireNonNull(version);
        this.messageType = requireNonNull(messageType);
        this.payload = requireNonNull(payload);
    }

    public String encoded(){
        return new StringBuilder()
            .append(randomValue).append(FIELD_DELIMITER)
            .append(encode(username)).append(FIELD_DELIMITER)