如何从Java生成ssh兼容的id_rsa(.pub)

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中编码返回的字节数组.

对于私钥编码,有两种情况:

  1. 私钥不受密码保护.在这种情况下,私钥根据PKCS#8标准进行编码,然后使用Base64进行编码.它可以通过打电话来获得私钥的PKCS8编码getEncodedRSAPrivateKey.
  2. 私钥受密码保护.在这种情况下,密钥编码是OpenSSH专用格式.我不知道是否有关于此格式的任何文档(当然,除了OpenSSH源代码)

  • 非常感谢.我还找到了jsch(http://www.jcraft.com/jsch/),一个提供此功能的免费库. (4认同)

use*_*104 5

gotoalberto对不同问题的回答(引用如下)适用于 RSA 和 DSA 密钥:

如果您想反转该过程,PublicKey即将 Java 对象编码为 Linuxauthorized_keys条目格式,可以使用以下代码:

    /**
     * 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());
        }
    }
Run Code Online (Sandbox Code Playgroud)