
org.apache.brooklyn.util.crypto.AuthorizedKeysParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of brooklyn-utils-common Show documentation
Show all versions of brooklyn-utils-common Show documentation
Utility classes and methods developed for Brooklyn but not dependendent on Brooklyn or much else
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.brooklyn.util.crypto;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.RSAPublicKeySpec;
import org.apache.brooklyn.util.exceptions.Exceptions;
import com.google.common.io.BaseEncoding;
public class AuthorizedKeysParser {
public static PublicKey decodePublicKey(String keyLine) {
try {
ByteArrayInputStream stream = null;
// 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")) {
stream = new ByteArrayInputStream(BaseEncoding.base64().decode(part));
break;
}
}
if (stream == null)
throw new IllegalArgumentException("Encoded public key should include phrase beginning AAAA.");
String type = readType(stream);
if (type.equals("ssh-rsa")) {
BigInteger e = readBigInt(stream, 1);
BigInteger m = readBigInt(stream, 1);
RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
return KeyFactory.getInstance("RSA").generatePublic(spec);
} else if (type.equals("ssh-dss")) {
BigInteger p = readBigInt(stream, 1);
BigInteger q = readBigInt(stream, 1);
BigInteger g = readBigInt(stream, 1);
BigInteger y = readBigInt(stream, 1);
DSAPublicKeySpec spec = new DSAPublicKeySpec(y, p, q, g);
return KeyFactory.getInstance("DSA").generatePublic(spec);
} else {
throw new IllegalArgumentException("Unknown public key type " + type);
}
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
throw new IllegalArgumentException("Error parsing authorized_keys/SSH2 format public key: "+e);
}
}
private static int readInt(InputStream stream) throws IOException {
return ((stream.read() & 0xFF) << 24) | ((stream.read() & 0xFF) << 16)
| ((stream.read() & 0xFF) << 8) | (stream.read() & 0xFF);
}
private static byte[] readBytesWithLength(InputStream stream, int minLen) throws IOException {
int len = readInt(stream);
if (len100000)
throw new IllegalStateException("Invalid stream header: length "+len);
byte[] result = new byte[len];
stream.read(result);
return result;
}
private static void writeInt(OutputStream stream, int v) throws IOException {
for (int shift = 24; shift >= 0; shift -= 8)
stream.write((v >>> shift) & 0xFF);
}
private static void writeBytesWithLength(OutputStream stream, byte[] buf) throws IOException {
writeInt(stream, buf.length);
stream.write(buf);
}
private static String readType(InputStream stream) throws IOException { return new String(readBytesWithLength(stream, 0)); }
private static BigInteger readBigInt(InputStream stream, int minLen) throws IOException { return new BigInteger(readBytesWithLength(stream, minLen)); }
public static String encodePublicKey(PublicKey key) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
String type = null;
if (key==null) {
return null;
} else if (key instanceof RSAPublicKey) {
type = "ssh-rsa";
writeBytesWithLength(out, type.getBytes());
writeBytesWithLength(out, ((RSAPublicKey)key).getPublicExponent().toByteArray());
writeBytesWithLength(out, ((RSAPublicKey)key).getModulus().toByteArray());
} else if (key instanceof DSAPublicKey) {
type = "ssh-dss";
writeBytesWithLength(out, type.getBytes());
writeBytesWithLength(out, ((DSAPublicKey)key).getParams().getP().toByteArray());
writeBytesWithLength(out, ((DSAPublicKey)key).getParams().getQ().toByteArray());
writeBytesWithLength(out, ((DSAPublicKey)key).getParams().getG().toByteArray());
writeBytesWithLength(out, ((DSAPublicKey)key).getY().toByteArray());
} else {
throw new IllegalStateException("Unsupported public key type for encoding: "+key);
}
out.close();
return type+" "+BaseEncoding.base64().encode(out.toByteArray());
} catch (Exception e) {
// shouldn't happen, as it's a byte stream...
throw Exceptions.propagate(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy