All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bitcoinj.crypto.BLSPublicKey Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2019 Dash Core Group.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bitcoinj.crypto;

import com.google.common.base.Preconditions;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.ProtocolException;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;
import org.dashj.bls.DASHJBLS;
import org.dashj.bls.G1Element;
import org.dashj.bls.G1ElementVector;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * This class wraps a G1Element in the BLS library
 */

public class BLSPublicKey extends BLSAbstractObject {
    public static final int BLS_CURVE_PUBKEY_SIZE  = 48;
    G1Element publicKeyImpl;

    public BLSPublicKey() {
        super(BLS_CURVE_PUBKEY_SIZE);
    }
    public BLSPublicKey(G1Element pk) {
        this(pk, false);
    }

    public BLSPublicKey(G1Element pk, boolean legacy) {
        super(BLS_CURVE_PUBKEY_SIZE);
        valid = true;
        publicKeyImpl = pk;
        this.legacy = legacy;
        updateHash();
    }

    /**
     *
     * @param publicKey the bytes for the public key in basic scheme
     */
    public BLSPublicKey(byte [] publicKey) {
        this(publicKey, false);
    }
    public static BLSPublicKey fromSerializedBytes(byte [] publicKey) {
        boolean legacy;
        if (publicKey.length == BLS_CURVE_PUBKEY_SIZE + 1) {
            legacy = publicKey[0] != 0;
            publicKey = Arrays.copyOfRange(publicKey, 1, publicKey.length);
        } else {
            throw new IllegalArgumentException("serialized public key should be 49 bytes but is " + publicKey.length + " bytes");
        }
        return new BLSPublicKey(publicKey, legacy);
    }

    public BLSPublicKey(byte [] publicKey, boolean legacy) {
        super(BLS_CURVE_PUBKEY_SIZE);
        Preconditions.checkArgument(publicKey.length == BLS_CURVE_PUBKEY_SIZE);
        publicKeyImpl = G1Element.fromBytes(publicKey, legacy);
        valid = true;
        this.legacy = legacy;
        updateHash();
    }

    public BLSPublicKey(String publicKeyHex, boolean legacy) {
        this(Utils.HEX.decode(publicKeyHex), legacy);
    }

    public BLSPublicKey(NetworkParameters params, byte [] payload, int offset) {
        super(params, payload, offset, false);
    }

    public BLSPublicKey(NetworkParameters params, byte [] payload, int offset, boolean legacy) {
        super(params, payload, offset, legacy);
    }

    public BLSPublicKey(BLSPublicKey publicKey) {
        super(publicKey.getBuffer(), BLS_CURVE_PUBKEY_SIZE, publicKey.legacy);
    }

    @Override
    boolean internalSetBuffer(byte[] buffer) {
        try {
            publicKeyImpl = G1Element.fromBytes(buffer, legacy);
            return true;
        } catch (Exception x) {
            // try again
            try {
                publicKeyImpl = G1Element.fromBytes(buffer, legacy);
                return true;
            } catch (Exception x2) {
                return false;
            }
        }
    }

    @Override
    boolean internalGetBuffer(byte[] buffer, boolean legacy) {
        byte [] serialized = publicKeyImpl.serialize(legacy);
        System.arraycopy(serialized, 0, buffer, 0, buffer.length);
        return true;
    }

    @Override
    protected void parse() throws ProtocolException {
        super.parse();
        byte[] buffer = readBytes(BLS_CURVE_PUBKEY_SIZE);
        valid = internalSetBuffer(buffer);
        serializedSize = BLS_CURVE_PUBKEY_SIZE;
        length = cursor - offset;
    }

    @Override
    protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
        super.bitcoinSerializeToStream(stream);
    }

    public byte[] serialize(boolean legacy) {
        return publicKeyImpl.serialize(legacy);
    }

    public void aggregateInsecure(BLSPublicKey sk) {
        Preconditions.checkState(valid && sk.valid);
        publicKeyImpl = BLSScheme.get(BLSScheme.isLegacyDefault()).aggregate(
                new G1ElementVector(
                        new G1Element[]{publicKeyImpl, sk.publicKeyImpl}
                )
        );
        updateHash();
    }

    public static BLSPublicKey aggregateInsecure(ArrayList pks, boolean legacy) {
        if(pks.isEmpty()) {
            return new BLSPublicKey();
        }

        G1ElementVector publicKeys = new G1ElementVector();
        for(BLSPublicKey sk : pks) {
            publicKeys.add(sk.publicKeyImpl);
        }

        G1Element agg = BLSScheme.get(legacy).aggregate(publicKeys);

        return new BLSPublicKey(agg);
    }

    public boolean publicKeyShare(ArrayList mpk, BLSId id) {
        valid = false;
        updateHash();

        if(!id.valid)
            return false;

        G1ElementVector mpkVec = new G1ElementVector();
        for(BLSPublicKey pk : mpk) {
            if(!pk.valid)
                return false;
            mpkVec.add(pk.publicKeyImpl);
        }

        try {
            publicKeyImpl = DASHJBLS.publicKeyShare(mpkVec, id.hash.getBytes());
        } catch (Exception x) {
            return false;
        }

        valid = true;
        updateHash();
        return true;
    }

    public boolean setDHKeyExchange(BLSSecretKey sk, BLSPublicKey pk)
    {
        valid = false;
        hash = Sha256Hash.ZERO_HASH;

        if (!sk.valid || !pk.valid) {
            return false;
        }
        publicKeyImpl = DASHJBLS.multiply(sk.privateKey, pk.publicKeyImpl);
        valid = true;
        updateHash();
        return true;
    }

    public static BLSPublicKey dHKeyExchange(BLSSecretKey sk, BLSPublicKey pk) {
        if (!sk.valid || !pk.valid) {
            return null;
        }
        return new BLSPublicKey(DASHJBLS.multiply(sk.privateKey, pk.publicKeyImpl));
    }

    public long getFingerprint() {
        return publicKeyImpl.getFingerprint(false);
    }

    public long getFingerprint(boolean legacy) {
        return publicKeyImpl.getFingerprint(legacy);
    }

    @Override
    public boolean isLegacy() {
        return legacy;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        BLSPublicKey that = (BLSPublicKey) o;
        if (publicKeyImpl == that.publicKeyImpl) {
            return true;
        }
        return DASHJBLS.objectEquals(publicKeyImpl, that.publicKeyImpl);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy