12

OK、これは「どこから始めればいいのかわからない」という質問の1つなので、答えが簡単なことを願っています。しかし、何を検索すればよいのかよくわからないので、これまでのところあまり役に立たなかった。

(現在ディスク上にある)ファイルから秘密鍵を読み取りたい。最終的にはキーはデータベースに存在しますが、これは今のところ十分であり、その違いはキーマテリアルの解析に実際には関係がないはずです。キーのパブリック部分(デバッガーで確認済み)を保持するインスタンスを作成できましたCredentialが、プライベート部分の読み取り方法がわからないようです。キーペアは次のように生成されました。

openssl genrsa 512 > d:\host.key
openssl req -new -x509 -nodes -sha1 -days 365 -key d:\host.key > d:\host.cert

はい、512ビットのRSAキーがずっと前に壊れていたことを知っています。しかし、APIを機能させるために、システムエントロピーの供給を不必要に使い果たす理由はありません。)

これまでのコードは次のとおりです。

import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.security.x509.BasicX509Credential;

private Credential getSigningCredential()
throws java.security.cert.CertificateException, IOException {
    BasicX509Credential credential = new BasicX509Credential();

    credential.setUsageType(UsageType.SIGNING);

    // read public key
    InputStream inStream = new FileInputStream("d:\\host.cert");
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
    inStream.close();
    credential.setEntityCertificate(cert);

    // TODO: read private key

    // done.
    return credential;
}

host.keyしかし、ファイルをの秘密鍵部分に読み込んでcredential、生成されたCredentialインスタンスを使用してデータに署名できるようにするにはどうすればよいですか?

4

2 に答える 2

21

BasicX509Credential標準 Java の一部ではありません。org.opensaml.xml.security.x509.BasicX509CredentialOpenSAMLから話していると思います。

PrivateKeyで設定する が必要ですcredential.setPrivateKey()。を取得するPrivateKeyには、まず秘密鍵を Java が読み取れる形式、つまり PKCS#8 に変換する必要があります。

openssl pkcs8 -topk8 -nocrypt -outform DER < D:\host.key > D:\host.pk8

次に、Java から:

RandomAccessFile raf = new RandomAccessFile("d:\\host.pk8", "r");
byte[] buf = new byte[(int)raf.length()];
raf.readFully(buf);
raf.close();
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(buf);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(kspec);

そしてほら!あなたはあなたを持っていますPrivateKey

デフォルトでopensslは、独自の形式でキーを書き込み (RSA キーの場合、PKCS#8 はたまたまその形式のラッパーになります)、それらPEM でエンコードします。これはヘッダーとフッターを含む Base64 です。どちらの特性もプレーン Java ではサポートされていないため、PKCS#8 に変換されます。この-nocryptオプションは、PKCS#8 が秘密鍵のオプションのパスワードベースの暗号化をサポートしているためです。

警告:本当はもっと長い RSA キーを使いたがっています512 ビットは弱いです。512 ビットの RSA キーは、1999 年に数百台のコンピューターで破られました。2011 年、12 年間の技術的進歩により、512 ビットの RSA キーはほとんど誰でも破ることができると想定する必要があります。したがって、少なくとも1024 ビットの RSA キーを使用してください (できれば 2048 ビットです。キーを使用するときの計算オーバーヘッドはそれほど悪くなく、1 秒あたり数百の署名を実行できます)。

于 2011-03-08T14:19:26.073 に答える
1

この質問はSAMLに関連しており、XMLObjectに署名するための秘密鍵を取得したい人にも関係があります。上記の答えはうまく機能し、キーストアから秘密鍵を取得することも可能です。

        Properties sigProperties = new Properties();

    sigProperties.put("org.apache.ws.security.crypto.provider","org.apache.ws.security.components.crypto.Merlin");
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.type","jks");
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.password","keypass");
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.alias","keyalias");
    sigProperties.put("org.apache.ws.security.crypto.merlin.keystore.file","keystore.jks");

    Crypto issuerCrypto = CryptoFactory.getInstance(sigProperties);

    String issuerKeyName = (String) sigProperties.get("org.apache.ws.security.crypto.merlin.keystore.alias");

    //See http://ws.apache.org/wss4j/xref/org/apache/ws/security/saml/ext/AssertionWrapper.html 'signAssertion' method
    // prepare to sign the SAML token
    CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
    cryptoType.setAlias(issuerKeyName);
    X509Certificate[] issuerCerts = issuerCrypto.getX509Certificates(cryptoType);
    if (issuerCerts == null) {
        throw new WSSecurityException(
                "No issuer certs were found to sign the SAML Assertion using issuer name: "
                        + issuerKeyName);
    }

    String password = ADSUnitTestUtils.getPrivateKeyPasswordFromAlias(issuerKeyName);

    PrivateKey privateKey = null;
    try {
        privateKey = issuerCrypto.getPrivateKey(issuerKeyName, password);
    } catch (Exception ex) {
        throw new WSSecurityException(ex.getMessage(), ex);
    }


    BasicX509Credential signingCredential = new BasicX509Credential();
    signingCredential.setEntityCertificate(issuerCerts[0]);
    signingCredential.setPrivateKey(privateKey);

    signature.setSigningCredential(signingCredential);

これは、要求された元のクエリよりも多くのコードですが、BasicX509Credentialを取得しようとしているようです。

ありがとう、ヨゲシュ

于 2012-12-14T17:16:38.177 に答える