代码之家  ›  专栏  ›  技术社区  ›  Carsten

如何从Java生成ssh兼容的id\u rsa(.pub)

  •  13
  • Carsten  · 技术社区  · 14 年前

    我正在寻找一种方法,以编程方式创建ssh兼容的id\u rsa和id_rsa.pub公司Java文件。

    我已经创造了钥匙对:

    KeyPairGenerator generator;
    generator = KeyPairGenerator.getInstance("RSA");
    // or: generator = KeyPairGenerator.getInstance("DSA");
    generator.initialize(2048);
    keyPair = generator.genKeyPair();
    

    但是,我不知道如何在密钥对中创建PrivateKey和PublicKey的字符串表示。

    4 回复  |  直到 9 年前
        1
  •  28
  •   Duncan Jones    12 年前

    ssh使用的密钥格式在 RFC #4253 . RSA公钥的格式如下:

      string    "ssh-rsa"
      mpint     e /* key public exponent */
      mpint     n /* key modulus */
    

    所有数据类型编码都在的第5节中定义 RFC #4251 . 字符串和mpint(多精度整数)类型的编码方式如下:

      4-bytes word: data length (unsigned big-endian 32 bits integer)
      n bytes     : binary representation of the data
    

      byte[] data = new byte[] {0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a'};
    

    为公众编码:

       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);
       }
    

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

    1. 私钥不受密码保护。在这种情况下,私钥根据PKCS#8标准进行编码,然后使用Base64进行编码。可以通过调用 getEncoded RSAPrivateKey .
    2. 私钥受密码保护。在这种情况下,密钥编码是OpenSSH专用格式。我不知道是否有这种格式的文档(当然除了OpenSSH源代码)
        2
  •  4
  •   ymnk    13 年前

    正如Carsten所提到的,JSch可以很容易地生成这些密钥对。 参考它的例子, KeyGen.java

        3
  •  4
  •   Community CDub    8 年前

    gotoalberto answer (以下引用)对于不同的问题,RSA和DSA密钥都适用:

    如果你想反转这个过程,也就是编码一个 PublicKey Java对象 到Linux authorized_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());
            }
        }
    
        4
  •  2
  •   Raul Santelices    8 年前

    任何问题的通用解决方案 PublicKey 类型(RSA、DSA等)是一个使用SSHJ的一行程序:

    byte[] b = new Buffer.PlainBuffer().putPublicKey(key).getCompactData()
    

    Base64.getEncoder().encodeToString(b) .