// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int cipherTextBlockSize = 16;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final Decoder decoder = getUrlDecoder();
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final Encoder encoder = getUrlEncoder();
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int initializationVectorBytes = 16;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int minimumTokenBytes = tokenStaticBytes + cipherTextBlockSize;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int signatureBytes = 32;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final byte supportedVersion = (byte) 0x80;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int tokenStaticBytes = versionBytes + timestampBytes + initializationVectorBytes + signatureBytes;


import static com.macasaet.fernet.Constants.charset;
import static com.macasaet.fernet.Constants.cipherTextBlockSize;
import static com.macasaet.fernet.Constants.decoder;
import static com.macasaet.fernet.Constants.encoder;
import static com.macasaet.fernet.Constants.initializationVectorBytes;
import static com.macasaet.fernet.Constants.minimumTokenBytes;
import static com.macasaet.fernet.Constants.signatureBytes;
import static com.macasaet.fernet.Constants.supportedVersion;
import static com.macasaet.fernet.Constants.tokenStaticBytes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.Base64.Encoder;
import java.util.Collection;
import javax.crypto.spec.IvParameterSpec;
            throw new IllegalTokenException("timestamp cannot be null");
        }
        if (initializationVector == null || initializationVector.getIV().length != initializationVectorBytes) {
            throw new IllegalTokenException("Initialization Vector must be 128 bits");
        }
        if (cipherText == null || cipherText.length % cipherTextBlockSize != 0) {
            throw new IllegalTokenException("Ciphertext must be a multiple of 128 bits");
        }
        if (hmac == null || hmac.length != signatureBytes) {
            throw new IllegalTokenException("hmac must be 256 bits");
        }
        this.version = version;
        this.timestamp = timestamp;
        this.initializationVector = initializationVector;
        this.cipherText = cipherText;
        this.hmac = hmac;
    }

    /**
     * Read a Token from bytes. This does NOT validate that the token was
     * generated using a valid {@link Key}.
     *
     * @param bytes a Fernet token in the form Version | Timestamp | IV |
     *              Ciphertext | HMAC
     * @return a new Token
     * @throws IllegalTokenException if the input string cannot be a valid
     *                               token irrespective of key or timestamp.
     */
    @SuppressWarnings({"PMD.PrematureDeclaration", "PMD.DataflowAnomalyAnalysis"})
    public static Token fromBytes(final byte[] bytes) {
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int cipherTextBlockSize = 16;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final Decoder decoder = getUrlDecoder();
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final Encoder encoder = getUrlEncoder();
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int initializationVectorBytes = 16;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int minimumTokenBytes = tokenStaticBytes + cipherTextBlockSize;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int signatureBytes = 32;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final byte supportedVersion = (byte) 0x80;
// 
// Path: fernet-java8/src/main/java/com/macasaet/fernet/Constants.java
// static final int tokenStaticBytes = versionBytes + timestampBytes + initializationVectorBytes + signatureBytes;


// Path: fernet-java8/src/main/java/com/macasaet/fernet/Token.java
import static com.macasaet.fernet.Constants.charset;
import static com.macasaet.fernet.Constants.cipherTextBlockSize;
import static com.macasaet.fernet.Constants.decoder;
import static com.macasaet.fernet.Constants.encoder;
import static com.macasaet.fernet.Constants.initializationVectorBytes;
import static com.macasaet.fernet.Constants.minimumTokenBytes;
import static com.macasaet.fernet.Constants.signatureBytes;
import static com.macasaet.fernet.Constants.supportedVersion;
import static com.macasaet.fernet.Constants.tokenStaticBytes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.Base64.Encoder;
import java.util.Collection;
import javax.crypto.spec.IvParameterSpec;

            throw new IllegalTokenException("timestamp cannot be null");
        }
        if (initializationVector == null || initializationVector.getIV().length != initializationVectorBytes) {
            throw new IllegalTokenException("Initialization Vector must be 128 bits");
        }
        if (cipherText == null || cipherText.length % cipherTextBlockSize != 0) {
            throw new IllegalTokenException("Ciphertext must be a multiple of 128 bits");
        }
        if (hmac == null || hmac.length != signatureBytes) {
            throw new IllegalTokenException("hmac must be 256 bits");
        }
        this.version = version;
        this.timestamp = timestamp;
        this.initializationVector = initializationVector;
        this.cipherText = cipherText;
        this.hmac = hmac;
    }

    /**
     * Read a Token from bytes. This does NOT validate that the token was
     * generated using a valid {@link Key}.
     *
     * @param bytes a Fernet token in the form Version | Timestamp | IV |
     *              Ciphertext | HMAC
     * @return a new Token
     * @throws IllegalTokenException if the input string cannot be a valid
     *                               token irrespective of key or timestamp.
     */
    @SuppressWarnings({"PMD.PrematureDeclaration", "PMD.DataflowAnomalyAnalysis"})
    public static Token fromBytes(final byte[] bytes) {
        if (bytes.length < minimumTokenBytes) {