package diskCacheV111.util; import java.math.BigInteger; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.spec.DSAPublicKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.util.Base64; /** * {@link AuthorizedKeyParser} creates a {@link PublicKey} representation of a * string representation that could originate from e.g. a authorized_keys file. * * @author bernardt * */ public class AuthorizedKeyParser { private byte[] bytes; private int pos; /** * * @param Takes * a line of a key file - keyLine * @return It then returns a {@link PublicKey} representation of either the * RSA or DSA key. * @throws NoSuchAlgorithmException * if algorithm is not known (known are RSA, DSA) * @throws InvalidKeySpecException */ public PublicKey decodePublicKey(String keyLine) throws IllegalArgumentException, InvalidKeySpecException, NoSuchAlgorithmException { bytes = null; pos = 0; // look for the Base64 encoded part of the line to decode // both ssh-rsa and ssh-dss begin with "AAAA" due to the length bytes for (String part : keyLine.split(" ")) { if (part.startsWith("AAAA")) { bytes = Base64.getDecoder().decode(part); break; } } if (bytes == null) { throw new IllegalArgumentException("no Base64 part to decode"); } String type = decodeType(); switch (type) { case "ssh-rsa": { BigInteger e = decodeBigInt(); BigInteger m = decodeBigInt(); RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e); return KeyFactory.getInstance("RSA").generatePublic(spec); } case "ssh-dss": { BigInteger p = decodeBigInt(); BigInteger q = decodeBigInt(); BigInteger g = decodeBigInt(); BigInteger y = decodeBigInt(); DSAPublicKeySpec spec = new DSAPublicKeySpec(y, p, q, g); return KeyFactory.getInstance("DSA").generatePublic(spec); } default: throw new IllegalArgumentException("unknown type " + type); } } private String decodeType() { int len = decodeInt(); String type = new String(bytes, pos, len); pos += len; return type; } private int decodeInt() { return ((bytes[pos++] & 0xFF) << 24) | ((bytes[pos++] & 0xFF) << 16) | ((bytes[pos++] & 0xFF) << 8) | (bytes[pos++] & 0xFF); } private BigInteger decodeBigInt() { int len = decodeInt(); byte[] bigIntBytes = new byte[len]; System.arraycopy(bytes, pos, bigIntBytes, 0, len); pos += len; return new BigInteger(bigIntBytes); } }