com.sshtools.ssh.components.jce.Ssh2DsaPublicKey Maven / Gradle / Ivy
The newest version!
/**
* Copyright 2003-2016 SSHTOOLS Limited. All Rights Reserved.
*
* For product documentation visit https://www.sshtools.com/
*
* This file is part of J2SSH Maverick.
*
* J2SSH Maverick is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* J2SSH Maverick is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with J2SSH Maverick. If not, see .
*/
package com.sshtools.ssh.components.jce;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import com.sshtools.ssh.SshException;
import com.sshtools.ssh.SshKeyFingerprint;
import com.sshtools.ssh.components.SshDsaPublicKey;
import com.sshtools.ssh.components.SshPublicKey;
import com.sshtools.util.ByteArrayReader;
import com.sshtools.util.ByteArrayWriter;
import com.sshtools.util.SimpleASNWriter;
/**
* A DSA public key implementation which uses a JCE provider.
*
* @author Lee David Painter
*/
public class Ssh2DsaPublicKey implements SshDsaPublicKey {
protected DSAPublicKey pubkey;
public Ssh2DsaPublicKey() {
}
public Ssh2DsaPublicKey(DSAPublicKey pub) {
this.pubkey = pub;
}
public Ssh2DsaPublicKey(BigInteger p, BigInteger q, BigInteger g,
BigInteger y) throws NoSuchAlgorithmException,
InvalidKeySpecException {
KeyFactory keyFactory = JCEProvider
.getProviderForAlgorithm(JCEAlgorithms.JCE_DSA) == null ? KeyFactory
.getInstance(JCEAlgorithms.JCE_DSA) : KeyFactory.getInstance(
JCEAlgorithms.JCE_DSA,
JCEProvider.getProviderForAlgorithm(JCEAlgorithms.JCE_DSA));
KeySpec publicKeySpec = new DSAPublicKeySpec(y, p, q, g);
pubkey = (DSAPublicKey) keyFactory.generatePublic(publicKeySpec);
}
/**
* Get the algorithm name for the public key.
*
* @return the algorithm name, for example "ssh-dss"
* @todo Implement this com.sshtools.ssh.SshPublicKey method
*/
public String getAlgorithm() {
return "ssh-dss";
}
/**
*
* @return the bit length of the public key
* @todo Implement this com.sshtools.ssh.SshPublicKey method
*/
public int getBitLength() {
return pubkey.getParams().getP().bitLength();
}
/**
* Encode the public key into a blob of binary data, the encoded result will
* be passed into init to recreate the key.
*
* @return an encoded byte array
* @throws SshException
* @todo Implement this com.sshtools.ssh.SshPublicKey method
*/
public byte[] getEncoded() throws SshException {
ByteArrayWriter baw = new ByteArrayWriter();
try {
baw.writeString(getAlgorithm());
baw.writeBigInteger(pubkey.getParams().getP());
baw.writeBigInteger(pubkey.getParams().getQ());
baw.writeBigInteger(pubkey.getParams().getG());
baw.writeBigInteger(pubkey.getY());
return baw.toByteArray();
} catch (IOException ioe) {
throw new SshException("Failed to encoded DSA key",
SshException.INTERNAL_ERROR, ioe);
} finally {
try {
baw.close();
} catch (IOException e) {
}
}
}
/**
*
* @return java.lang.String
* @throws SshException
* @todo Implement this com.sshtools.ssh.SshPublicKey method
*/
public String getFingerprint() throws SshException {
return SshKeyFingerprint.getFingerprint(getEncoded());
}
/**
* Initialize the public key from a blob of binary data.
*
* @param blob
* byte[]
* @param start
* int
* @param len
* int
* @throws SshException
* @todo Implement this com.sshtools.ssh.SshPublicKey method
*/
public void init(byte[] blob, int start, int len) throws SshException {
ByteArrayReader bar = new ByteArrayReader(blob, start, len);
try {
DSAPublicKeySpec dsaKey;
// Extract the key information
String header = bar.readString();
if (!header.equals(getAlgorithm())) {
throw new SshException("The encoded key is not DSA",
SshException.INTERNAL_ERROR);
}
BigInteger p = bar.readBigInteger();
BigInteger q = bar.readBigInteger();
BigInteger g = bar.readBigInteger();
BigInteger y = bar.readBigInteger();
dsaKey = new DSAPublicKeySpec(y, p, q, g);
KeyFactory kf = JCEProvider
.getProviderForAlgorithm(JCEAlgorithms.JCE_DSA) == null ? KeyFactory
.getInstance(JCEAlgorithms.JCE_DSA) : KeyFactory
.getInstance(JCEAlgorithms.JCE_DSA, JCEProvider
.getProviderForAlgorithm(JCEAlgorithms.JCE_DSA));
pubkey = (DSAPublicKey) kf.generatePublic(dsaKey);
} catch (Exception ex) {
throw new SshException(
"Failed to obtain DSA key instance from JCE",
SshException.INTERNAL_ERROR, ex);
} finally {
try {
bar.close();
} catch (IOException e) {
}
}
}
/**
* Verify the signature.
*
* @param signature
* byte[]
* @param data
* byte[]
* @return true
if the signature was produced by the
* corresponding private key that owns this public key, otherwise
* false
.
* @throws SshException
* @todo Implement this com.sshtools.ssh.SshPublicKey method
*/
public boolean verifySignature(byte[] signature, byte[] data)
throws SshException {
ByteArrayReader bar = new ByteArrayReader(signature);
try {
if (signature.length != 40 // 160 bits
&& signature.length != 56 // 224 bits
&& signature.length != 64) { // 256 bits
byte[] sig = bar.readBinaryString();
// log.debug("Signature blob is " + new String(sig));
String header = new String(sig);
if (!header.equals("ssh-dss")) {
throw new SshException("The encoded signature is not DSA",
SshException.INTERNAL_ERROR);
}
signature = bar.readBinaryString();
}
int numSize = signature.length / 2;
// Using a SimpleASNWriter
ByteArrayOutputStream r = new ByteArrayOutputStream();
ByteArrayOutputStream s = new ByteArrayOutputStream();
SimpleASNWriter asn = new SimpleASNWriter();
asn.writeByte(0x02);
if (((signature[0] & 0x80) == 0x80) && (signature[0] != 0x00)) {
r.write(0);
r.write(signature, 0, numSize);
} else {
r.write(signature, 0, numSize);
}
asn.writeData(r.toByteArray());
asn.writeByte(0x02);
if (((signature[numSize] & 0x80) == 0x80)
&& (signature[numSize] != 0x00)) {
s.write(0);
s.write(signature, numSize, numSize);
} else {
s.write(signature, numSize, numSize);
}
asn.writeData(s.toByteArray());
SimpleASNWriter asnEncoded = new SimpleASNWriter();
asnEncoded.writeByte(0x30);
asnEncoded.writeData(asn.toByteArray());
byte[] encoded = asnEncoded.toByteArray();
Signature sig = JCEProvider
.getProviderForAlgorithm(JCEAlgorithms.JCE_SHA1WithDSA) == null ? Signature
.getInstance(JCEAlgorithms.JCE_SHA1WithDSA)
: Signature
.getInstance(
JCEAlgorithms.JCE_SHA1WithDSA,
JCEProvider
.getProviderForAlgorithm(JCEAlgorithms.JCE_SHA1WithDSA));
sig.initVerify(pubkey);
sig.update(data);
return sig.verify(encoded);
} catch (Exception ex) {
throw new SshException(SshException.JCE_ERROR, ex);
} finally {
try {
bar.close();
} catch (IOException e) {
}
}
}
public boolean equals(Object obj) {
if (obj instanceof SshDsaPublicKey) {
try {
return (((SshPublicKey) obj).getFingerprint()
.equals(getFingerprint()));
} catch (SshException ex) {
}
}
return false;
}
public int hashCode() {
try {
return getFingerprint().hashCode();
} catch (SshException ex) {
return 0;
}
}
public BigInteger getG() {
return pubkey.getParams().getG();
}
public BigInteger getP() {
return pubkey.getParams().getP();
}
public BigInteger getQ() {
return pubkey.getParams().getQ();
}
public BigInteger getY() {
return pubkey.getY();
}
}