/*
 * Class: DSAFormat
 *
 * Author: Alex Usun
 *
 * Date: 1/9/2005
 */
package com.jscape.inet.ssh.util.keyreader.vandyke;

import com.jscape.inet.ssh.util.keyreader.KeyPairSpec;
import com.jscape.util.Assert;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;

/**
 * VanDyke DSA key pair format.
 *
 * @author Alex Usun
 * @version 1.0
 * @see <a href="DSAFormat.java.html">Source code</a>
 */
public final class DSAFormat
        extends VanDykeFormat {

    private static final String ALGORITHM = "DSA";
    private static final String SSH_ALGORITHM = "ssh-dss";

    /**
     * @see com.jscape.inet.ssh.util.keyreader.vandyke.VanDykeFormat#getAlgorithm()
     */
    protected String getAlgorithm() {
        return ALGORITHM;
    }

    /**
     * @see VanDykeFormat#restoreKeyPair(Record)
     */
    protected KeyPairSpec restoreKeyPair(Record record)
            throws IOException {
        DSAPublicKeySpec pubSpec = restorePublicKeySpec(record.getPublicKeyData());
        DSAPrivateKeySpec privSpec = restorePrivateKeySpec(record.getPrivateKeyData(), pubSpec);

        return new KeyPairSpec(ALGORITHM, pubSpec, privSpec);
    }

    /**
     * Restores public key specification.
     *
     * @param data specification data
     *
     * @return restored specification
     *
     * @throws IOException if specification cannot be read
     */
    private DSAPublicKeySpec restorePublicKeySpec(byte[] data)
            throws IOException {
        DataReader reader = new DataReader(new ByteArrayInputStream(data));

        String algorithm = reader.readString();
        Assert.isTrue(SSH_ALGORITHM.equalsIgnoreCase(algorithm), "wrong key pair algorithm");

        BigInteger p = reader.readMpint();
        BigInteger q = reader.readMpint();
        BigInteger g = reader.readMpint();
        BigInteger y = reader.readMpint();

        return new DSAPublicKeySpec(y, p, q, g);
    }

    /**
     * Restores private key specification.
     *
     * @param data    specification data
     * @param pubSpec public key specification
     *
     * @return restored specification
     *
     * @throws IOException if specification cannot be read
     */
    private DSAPrivateKeySpec restorePrivateKeySpec(byte[] data, DSAPublicKeySpec pubSpec)
            throws IOException {
        DataReader reader = new DataReader(new ByteArrayInputStream(data));

        String algorithm = reader.readString();
        Assert.isTrue(SSH_ALGORITHM.equalsIgnoreCase(algorithm), "wrong key pair algorithm");

        reader.readMpint();
        reader.readMpint();
        reader.readMpint();
        BigInteger x = reader.readMpint();

        return new DSAPrivateKeySpec(x, pubSpec.getP(), pubSpec.getQ(), pubSpec.getG());
    }

}
