package com.jscape.inet.ssh.protocol.v2.marshaling.keys;

import com.jscape.inet.ssh.protocol.v2.marshaling.primitive.MpintCodec;
import com.jscape.inet.ssh.protocol.v2.marshaling.primitive.StringCodec;
import com.jscape.inet.ssh.protocol.v2.messages.Signature;
import com.jscape.util.io.ByteArrayInputStream;
import com.jscape.util.io.ByteArrayOutputStream;
import org.bouncycastle.asn1.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;

/**
 * @author Alex Usun
 */
public class EcSignatureCodec
        implements SignatureCodec.EntryCodec {

    public static Signature readValue(String identifier, InputStream in)
            throws IOException {
        byte[] blob = StringCodec.readValue(in);
        InputStream blobIn = new ByteArrayInputStream(blob);
        byte[] rData = MpintCodec.readValue(blobIn).toByteArray();
        BigInteger r = new BigInteger(1, rData);
        byte[] sData = MpintCodec.readValue(blobIn).toByteArray();
        BigInteger s = new BigInteger(1, sData);

        ASN1EncodableVector vector = new ASN1EncodableVector();
        vector.add(new ASN1Integer(r));
        vector.add(new ASN1Integer(s));
        byte[] signatureBlob = new DERSequence(vector).getEncoded("DER");

        return new Signature(identifier, signatureBlob);
    }

    public static void writeValue(Signature value, OutputStream out)
            throws IOException {
        ASN1Sequence sequence = (ASN1Sequence) ASN1Primitive.fromByteArray(value.blob);
        BigInteger r = ((ASN1Integer) sequence.getObjectAt(0)).getPositiveValue();
        BigInteger s = ((ASN1Integer) sequence.getObjectAt(1)).getPositiveValue();

        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        MpintCodec.writeValue(r, buffer);
        MpintCodec.writeValue(s, buffer);

        StringCodec.writeValue(buffer.toByteArray(), out);
    }

    @Override
    public Signature read(String identifier, InputStream in)
            throws IOException {
        return readValue(identifier, in);
    }

    @Override
    public void write(Signature value, OutputStream out)
            throws IOException {
        writeValue(value, out);
    }

}
