package io.airlift.airship.coordinator.auth; import io.airlift.airship.coordinator.auth.ssh.DerWriter; import io.airlift.airship.coordinator.auth.ssh.SshDsaPublicKey; import io.airlift.airship.coordinator.auth.ssh.SshKeyReader; import java.io.IOException; import java.security.Signature; import java.util.Arrays; import static io.airlift.airship.coordinator.auth.ssh.DerType.SEQUENCE; public class DsaPublicKey extends PublicKey { private SshDsaPublicKey sshDsaPublicKey; public DsaPublicKey(String encodedKey, String comment) { super(encodedKey, comment); sshDsaPublicKey = new SshDsaPublicKey(key); } public String getType() { return "ssh-dss"; } public boolean verifySignature(byte[] signature, byte[] message) { try { Signature sha1withDSA = Signature.getInstance("SHA1withDSA"); sha1withDSA.initVerify(sshDsaPublicKey); sha1withDSA.update(message); byte[] decodedSignature = toJavaDsaSignature(signature); return sha1withDSA.verify(decodedSignature); } catch (Exception e) { return false; } } public static byte[] toJavaDsaSignature(byte[] signature) throws IOException { if (signature.length != 40) { // strip ssh envelope SshKeyReader reader = new SshKeyReader(signature); String signatureType = reader.readString(); if (!"ssh-dss".equals(signatureType)) { throw new IllegalArgumentException("Signature is not a ssh-dss signature, but is " + signatureType + " signature"); } signature = reader.readEntry(); } if (signature.length != 40) { throw new IllegalArgumentException("Invalid ssh dsa signature"); } // signature is two big endian unsigned 20-bit integers byte[] r = Arrays.copyOf(signature, 20); byte[] s = Arrays.copyOfRange(signature, 20, 40); // encode the signature in Java's DER format return toJavaDsaSignature(r, s); } private static byte[] toJavaDsaSignature(byte[] r, byte[] s) throws IOException { byte[] encodedNumbers = new DerWriter() .writeInteger(r) .writeInteger(s) .toByteArray(); return new DerWriter() .writeEntry(SEQUENCE, encodedNumbers) .toByteArray(); } }