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

org.hyperledger.fabric.client.identity.ECSignature Maven / Gradle / Ivy

/*
 * Copyright 2021 IBM All Rights Reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

package org.hyperledger.fabric.client.identity;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequenceGenerator;

final class ECSignature {
    private final ASN1Integer r;
    private final ASN1Integer s;

    static ECSignature fromBytes(final byte[] derSignature) throws GeneralSecurityException {
        try (ByteArrayInputStream inStream = new ByteArrayInputStream(derSignature);
                ASN1InputStream asnInputStream = new ASN1InputStream(inStream)) {
            ASN1Primitive asn1 = asnInputStream.readObject();

            if (!(asn1 instanceof ASN1Sequence)) {
                throw new GeneralSecurityException(
                        "Invalid signature type: " + asn1.getClass().getTypeName());
            }

            ASN1Sequence asn1Sequence = (ASN1Sequence) asn1;
            List signatureParts = StreamSupport.stream(asn1Sequence.spliterator(), false)
                    .map(ASN1Encodable::toASN1Primitive)
                    .filter(asn1Primitive -> asn1Primitive instanceof ASN1Integer)
                    .map(asn1Primitive -> (ASN1Integer) asn1Primitive)
                    .collect(Collectors.toList());
            if (signatureParts.size() != 2) {
                throw new GeneralSecurityException(
                        "Invalid signature. Expected 2 values but got " + signatureParts.size());
            }

            return new ECSignature(signatureParts.get(0), signatureParts.get(1));
        } catch (IOException e) {
            // Should not happen reading from ByteArrayInputStream
            throw new UncheckedIOException(e);
        }
    }

    ECSignature(final ASN1Integer r, final ASN1Integer s) {
        this.r = r;
        this.s = s;
    }

    public ASN1Integer getR() {
        return r;
    }

    public ASN1Integer getS() {
        return s;
    }

    public byte[] getBytes() {
        try (ByteArrayOutputStream bytesOut = new ByteArrayOutputStream()) {
            DERSequenceGenerator sequence = new DERSequenceGenerator(bytesOut);
            sequence.addObject(r);
            sequence.addObject(s);
            sequence.close();
            return bytesOut.toByteArray();
        } catch (IOException e) {
            // Should not happen writing to ByteArrayOutputStream
            throw new UncheckedIOException(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy