Car*_*ten 15 java ssh openssh public-key-encryption
我正在寻找一种在Java中以编程方式创建ssh兼容的id_rsa和id_rsa.pub文件的方法.
我创建了KeyPair:
KeyPairGenerator generator;
generator = KeyPairGenerator.getInstance("RSA");
// or: generator = KeyPairGenerator.getInstance("DSA");
generator.initialize(2048);
keyPair = generator.genKeyPair();
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚如何在KeyPair中创建PrivateKey和PublicKey的String表示.
Jcs*_*Jcs 26
ssh使用的密钥格式在RFC#4253中定义.RSA公钥的格式如下:
string "ssh-rsa"
mpint e /* key public exponent */
mpint n /* key modulus */
Run Code Online (Sandbox Code Playgroud)
所有数据类型编码都在RFC#4251的#5部分中定义.string和mpint(多个精度整数)类型以这种方式编码:
4-bytes word: data length (unsigned big-endian 32 bits integer)
n bytes : binary representation of the data
Run Code Online (Sandbox Code Playgroud)
例如,字符串"ssh-rsa"的编码是:
byte[] data = new byte[] {0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a'};
Run Code Online (Sandbox Code Playgroud)
对公众进行编码:
public byte[] encodePublicKey(RSAPublicKey key) throws IOException
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
/* encode the "ssh-rsa" string */
byte[] sshrsa = new byte[] {0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a'};
out.write(sshrsa);
/* Encode the public exponent */
BigInteger e = key.getPublicExponent();
byte[] data = e.toByteArray();
encodeUInt32(data.length, out);
out.write(data);
/* Encode the modulus */
BigInteger m = key.getModulus();
data = m.toByteArray();
encodeUInt32(data.length, out);
out.write(data);
return out.toByteArray();
}
public void encodeUInt32(int value, OutputStream out) throws IOException
{
byte[] tmp = new byte[4];
tmp[0] = (byte)((value >>> 24) & 0xff);
tmp[1] = (byte)((value >>> 16) & 0xff);
tmp[2] = (byte)((value >>> 8) & 0xff);
tmp[3] = (byte)(value & 0xff);
out.write(tmp);
}
Run Code Online (Sandbox Code Playgroud)
要有一个字符串représentation键只是在Base64中编码返回的字节数组.
对于私钥编码,有两种情况:
getEncoded上RSAPrivateKey.gotoalberto对不同问题的回答(引用如下)适用于 RSA 和 DSA 密钥:
如果您想反转该过程,
PublicKey即将 Java 对象编码为 Linuxauthorized_keys条目格式,可以使用以下代码:Run Code Online (Sandbox Code Playgroud)/** * Encode PublicKey (DSA or RSA encoded) to authorized_keys like string * * @param publicKey DSA or RSA encoded * @param user username for output authorized_keys like string * @return authorized_keys like string * @throws IOException */ public static String encodePublicKey(PublicKey publicKey, String user) throws IOException { String publicKeyEncoded; if(publicKey.getAlgorithm().equals("RSA")){ RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; ByteArrayOutputStream byteOs = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(byteOs); dos.writeInt("ssh-rsa".getBytes().length); dos.write("ssh-rsa".getBytes()); dos.writeInt(rsaPublicKey.getPublicExponent().toByteArray().length); dos.write(rsaPublicKey.getPublicExponent().toByteArray()); dos.writeInt(rsaPublicKey.getModulus().toByteArray().length); dos.write(rsaPublicKey.getModulus().toByteArray()); publicKeyEncoded = new String( Base64.encodeBase64(byteOs.toByteArray())); return "ssh-rsa " + publicKeyEncoded + " " + user; } else if(publicKey.getAlgorithm().equals("DSA")){ DSAPublicKey dsaPublicKey = (DSAPublicKey) publicKey; DSAParams dsaParams = dsaPublicKey.getParams(); ByteArrayOutputStream byteOs = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(byteOs); dos.writeInt("ssh-dss".getBytes().length); dos.write("ssh-dss".getBytes()); dos.writeInt(dsaParams.getP().toByteArray().length); dos.write(dsaParams.getP().toByteArray()); dos.writeInt(dsaParams.getQ().toByteArray().length); dos.write(dsaParams.getQ().toByteArray()); dos.writeInt(dsaParams.getG().toByteArray().length); dos.write(dsaParams.getG().toByteArray()); dos.writeInt(dsaPublicKey.getY().toByteArray().length); dos.write(dsaPublicKey.getY().toByteArray()); publicKeyEncoded = new String( Base64.encodeBase64(byteOs.toByteArray())); return "ssh-dss " + publicKeyEncoded + " " + user; } else{ throw new IllegalArgumentException( "Unknown public key encoding: " + publicKey.getAlgorithm()); } }