Debian OpenSSL脆弱性問題のまとめはこちらを、最新のSSLブラックリストの更新履歴のまとめはこちらをご覧ください。m(_ _)m

X.509からの変換ツールと同じような感じで、
PKCS#8 RSA 秘密鍵(PINの無いもの)のPEM型式から
SSH2公開鍵に変換したものをファイル出力するツールです。

SSH2の公開鍵による脆弱性検証ツール(dowkd.pl、ssh-vulnkey)などで
ご利用ください。

Trilead SSH ライブラリと Bouncy Castle JCE ライブラリを使います。

ソースコード


/*
 *
 * PKCS8PEMToSSHPubKey - generate SSH2 public key file from
 * PKCS#8 PEM RSA Private Key File
 *
 * 					Kenji URUSHIMA
 *					22-Mar-2008
 * 
 * 1. DESCRIPTION
 *
 *   OpenSSL and OpenSSH vulnerabilities are announced on May 15, 2008.
 *   http://www.us-cert.gov/current/index.html#debian_openssl_vulnerability
 *
 *   This tool helps you to check whether the key corresponding to
 *   the in your PKCS#8 RSA Private Key  is weak using OpenSSH key blacklist or
 *   checking tools.
 *
 * 2. REQUIREMENT
 *
 * - This works on Sun Java 1.4.x or later.
 * - Trilead Library 
 *   - This requires 3rd party open source SSH libary from Trilead.
 *     You can download it from http://www.trilead.com/
 *   - This was tested using Trilead SSH-2 for Java build 213.
 * - Bouncy Castle JCE Library
 *   - The library can be downloaded from 
 *     http://www.bouncycastle.org/java.html.
 * 
 * 4. COMPILE
 *
 * - add Trilead libery and BouncyCastle JCE to class path like this:
 *   % export CLASSPATH=$CLASSPATH:./trilead-ssh2-build213.jar;./bcprov-jdk16-138.jar;
 * - compile
 *   % javac PKCS8PEMToSSHPubKey.java
 *
 * 5. GENERATE SSH2 PUBLIC KEY FILE FROM PKCS#8 RSA PRIVATE KEY
 *
 * - A PKCS#8 private key file is a text file like following:
 *
 *    -----BEGIN RSA PRIVATE KEY-----
 *    MIICXAIBAAKBgQDl/LnqaBR7lirE3HDMt1GuJyN9XCBz2lEZthyxX65KBFGkZUiY
 *    ... snip ...
 *    yOP/meskyOYERsh9INI3T+1/QrG/a6p3KKgKonNPvPk=
 *    -----END RSA PRIVATE KEY-----
 *   
 * - run tool
 *
 *   % java PKCS8PEMToSSHPubKey aaa.p8.pem 
 *
 *   Then you can get SSH2 public key file "aaa.p8.pem.ssh.pub" using
 *   the private key in "aaa.p8.pem".
 *
 *   You can also specify user id for SSH key.
 *   % java PKCS8PEMToSSHPubKey aaa.p8.pem bar@bar
 *
 * 6. CHECK KEY WEEKNESS
 *
 * - You can check key weakness using "dowkd.pl" Perl script.
 *   % dowkd.pl file aaa.cer.ssh.pub
 *   If the key is weak you'll get "weak key" message.
 * 
 * 7. CONDITIONS
 *
 *   This is free software with ABSOLUTELY NO WARRANTY.
 *
 * 8. CHANGELOG
 *   - 22 May 2008: initial release
 */

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.math.BigInteger;
import java.security.Security;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import com.trilead.ssh2.signature.RSASHA1Verify;
import com.trilead.ssh2.signature.RSAPublicKey;
import com.trilead.ssh2.signature.DSASHA1Verify;
import com.trilead.ssh2.signature.DSAPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
import java.security.interfaces.RSAPrivateKey;
import sun.misc.BASE64Encoder;

// referring classes
// java.security.interfaces.RSAPublicKey
// java.security.interfaces.DSAPublicKey

public class PKCS8PEMToSSHPubKey {
  private static final String DEFAULT_ID = "foo@foo";

  public PKCS8PEMToSSHPubKey() {
  }

  public void convert(String p8File, String sshFile, String sshUserId) {
    if (sshUserId == null) sshUserId = DEFAULT_ID;

    if (Security.getProvider("BC") == null)
      Security.addProvider(new BouncyCastleProvider());
    
    java.security.interfaces.RSAPublicKey rsaPK = null;
    try {
      PEMReader pemReader = 
	new PEMReader(new BufferedReader(new FileReader(p8File)));
      Object obj = pemReader.readObject();

      if (! (obj instanceof KeyPair))
	throw new RuntimeException("can't create key pair from: " + p8File);

      KeyPair keyPair = (KeyPair)obj;
      
      rsaPK = (java.security.interfaces.RSAPublicKey)(keyPair.getPublic());
    } catch (Exception ex) {
      ex.printStackTrace();
      System.exit(1);
    }

    //String alg = pubkey.getAlgorithm();
    String sshKeyType = null;
    String key = null;

    BigInteger n = rsaPK.getModulus();
    BigInteger e = rsaPK.getPublicExponent();
    RSAPublicKey rsaSSHPK = new RSAPublicKey(e, n);

    byte[] rsaSSHPKbytes = null;
    try {
      rsaSSHPKbytes = new RSASHA1Verify().encodeSSHRSAPublicKey(rsaSSHPK);
    } catch (Exception ex) {
      System.out.println("Error: can't encode RSA SSH public key: " + 
			 ex.getMessage());
      System.exit(1);
    }

    key = this.getBase64WithoutNewline(rsaSSHPKbytes);
    sshKeyType = "ssh-rsa";

    this.saveSSHPubkeyFile(sshKeyType, key, sshUserId, sshFile);
  }

  private void saveSSHPubkeyFile(String header, String key, String id, String sshFile) {
    try {
      FileWriter fr = new FileWriter(sshFile);
      fr.write(header + " " + key + " " + id + "\n");
      fr.close();
    } catch (Exception ex) {
      System.out.println("Error: can't write ssh public key: " + 
			 sshFile + " " + ex.getMessage());
      System.exit(1);
    }
  }

  private String getBase64WithoutNewline(byte[] b) {
    BASE64Encoder encoder = new BASE64Encoder();
    String b64Str = encoder.encode(b);
    String result = null;
    result = b64Str.replaceAll("[\r\n]", "");
    result = result.replaceAll("[\n]", "");
    return result;
  }

  public static void main(String[] args) {
    String p8File = args[0];
    String sshFile = args[0] + ".ssh.pub";
    String sshUserId = null;

    if (args.length > 1) sshUserId = args[1];

    PKCS8PEMToSSHPubKey c2s = new PKCS8PEMToSSHPubKey();
    c2s.convert(p8File, sshFile, sshUserId);
  }
}
最終更新:2008年06月20日 10:57