17

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

ただし、KeyPairでPrivateKeyとPublicKeyの文字列表現を作成する方法がわかりません。

4

4 に答える 4

28

sshで使用されるキー形式は、RFC#4253で定義されています。RSA公開鍵の形式は次のとおりです。

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

すべてのデータ型エンコーディングは、RFC#4251のセクション#5で定義されています。文字列型とmpint(複数精度の整数)型は次のようにエンコードされます。

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

たとえば、文字列「ssh-rsa」のエンコーディングは次のとおりです。

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

キーの文字列表現を使用するには、返されたバイト配列をBase64でエンコードするだけです。

秘密鍵エンコーディングには、次の2つのケースがあります。

  1. 秘密鍵はパスワードで保護されていません。その場合、秘密鍵はPKCS#8標準に従ってエンコードされ、Base64でエンコードされます。を呼び出すことにより、秘密鍵のPKCS8エンコーディングを取得することができgetEncodedますRSAPrivateKey
  2. 秘密鍵はパスワードで保護されています。その場合、キーエンコーディングはOpenSSH専用フォーマットです。この形式に関するドキュメントがあるかどうかはわかりません(もちろんOpenSSHソースコードを除く)
于 2010-09-14T06:44:02.833 に答える
5

別の質問に対するgotoalberto回答(以下に引用)は、RSAキーとDSAキーの両方で機能します。

プロセスを逆にしたい場合、つまりPublicKeyJavaオブジェクトを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());
        }
    }
于 2014-04-11T14:21:55.747 に答える
4

Carstenが述べたように、JSchはそれらのキーペアを簡単に生成できます。その例、KeyGen.javaを参照してください

于 2012-04-27T00:43:22.310 に答える
2

あらゆるPublicKeyタイプ(RSA、DSAなど)の一般的なソリューションは、SSHJを使用したワンライナーです。

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

次に、を使用してエンコードしBase64.getEncoder().encodeToString(b)ます。

于 2017-04-07T22:09:39.623 に答える