net.java.otr4j.messages.SignatureX.java Source code

Java tutorial

Introduction

Here is the source code for net.java.otr4j.messages.SignatureX.java

Source

/*
 * otr4j, the open source java otr library.
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 *
 * SPDX-License-Identifier: LGPL-3.0-only
 */
package net.java.otr4j.messages;

import net.java.otr4j.crypto.OtrCryptoException;
import net.java.otr4j.io.OtrEncodable;
import net.java.otr4j.io.OtrOutputStream;
import org.bouncycastle.util.Arrays;

import javax.annotation.Nonnull;
import java.security.interfaces.DSAPublicKey;

import static java.util.Objects.requireNonNull;
import static net.java.otr4j.crypto.DSAKeyPair.DSA_SIGNATURE_LENGTH_BYTES;
import static net.java.otr4j.crypto.DSAKeyPair.verifySignature;
import static net.java.otr4j.util.ByteArrays.allZeroBytes;
import static net.java.otr4j.util.ByteArrays.constantTimeEquals;
import static net.java.otr4j.util.ByteArrays.requireLengthExactly;
import static net.java.otr4j.util.Integers.requireNotEquals;

/**
 * The payload representing the X value.
 *
 * @author George Politis
 */
public final class SignatureX implements OtrEncodable {

    @Nonnull
    private final DSAPublicKey longTermPublicKey;

    private final int dhKeyID;

    @Nonnull
    private final byte[] signature;

    /**
     * Constructor.
     *
     * @param ourLongTermPublicKey our long-term DSA public key
     * @param ourKeyID             our key ID
     * @param signature            the corresponding signature
     */
    @SuppressWarnings("NullAway") // FIXME remove once bug is fixed (https://github.com/uber/NullAway/issues/347)
    public SignatureX(final DSAPublicKey ourLongTermPublicKey, final int ourKeyID, final byte[] signature) {
        this.longTermPublicKey = requireNonNull(ourLongTermPublicKey);
        this.dhKeyID = requireNotEquals(0, ourKeyID);
        this.signature = requireLengthExactly(DSA_SIGNATURE_LENGTH_BYTES, signature);
        assert !allZeroBytes(
                this.signature) : "Expected non-zero bytes for signature. This may indicate that a critical bug is present, or it may be a false warning.";
    }

    /**
     * Get the long-term DSA public key.
     *
     * @return the long-term DSA public key.
     */
    @Nonnull
    public DSAPublicKey getLongTermPublicKey() {
        return longTermPublicKey;
    }

    /**
     * Get DH key id.
     *
     * @return Returns the DH key ID.
     */
    public int getDhKeyID() {
        return dhKeyID;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + dhKeyID;
        result = prime * result + longTermPublicKey.hashCode();
        result = prime * result + Arrays.hashCode(signature);
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final SignatureX other = (SignatureX) obj;
        if (dhKeyID != other.dhKeyID) {
            return false;
        }
        if (!longTermPublicKey.equals(other.longTermPublicKey)) {
            return false;
        }
        return constantTimeEquals(signature, other.signature);
    }

    /**
     * Verify expected signature with signature in SignatureX.
     *
     * @param expectedSignature the expected signature to verify against the SignatureX signature
     * @throws OtrCryptoException In case of failures of a cryptographic nature.
     */
    public void verify(final byte[] expectedSignature) throws OtrCryptoException {
        verifySignature(expectedSignature, this.longTermPublicKey, this.signature);
    }

    @Override
    public void writeTo(final OtrOutputStream out) {
        out.writePublicKey(this.longTermPublicKey);
        out.writeInt(this.dhKeyID);
        out.writeDSASignature(this.signature);
    }
}