JavaでeTokenを使う(その2)

まずは、eTokenでキーペアを作ってみる。providerとkeyStoreはすでに設定済みと言う前提で。

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.Calendar;
import javax.crypto.Cipher;
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateIssuerName;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateSubjectName;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateX509Key;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;


...

public void doGenerateKeyPair(String alias, String principal, String storePass,
				int keyLength, BigInteger serial)
		throws Exception {
		
    KeyPairGenerator kpgen = KeyPairGenerator.getInstance("RSA", provider);
    kpgen.initialize(keyLength);
    KeyPair kp = kpgen.generateKeyPair();

    Calendar cal = Calendar.getInstance();
    Calendar expire = (Calendar)cal.clone();
    expire.add(Calendar.DATE, 3650);
		
    X509CertInfo info = new X509CertInfo();
		
    CertificateValidity validity =
            new CertificateValidity(cal.getTime(), expire.getTime());
    info.set(X509CertInfo.VALIDITY, validity);
    info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serial));

    X500Name name = new X500Name(principal);
    CertificateIssuerName issuer = new CertificateIssuerName(name);
    CertificateSubjectName subject = new CertificateSubjectName(name);
    AlgorithmId alogoId = AlgorithmId.get(
            AlgorithmId.sha1WithRSAEncryption_oid.toString());

    info.set(X509CertInfo.ISSUER, issuer);
    info.set(X509CertInfo.SUBJECT, subject);
    info.set(X509CertInfo.KEY, new CertificateX509Key(kp.getPublic()));
    info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(alogoId));

    X509CertImpl target = new X509CertImpl(info);
    target.sign(kp.getPrivate(), alogoId.getName(), provider.getName());

    keyStore.setKeyEntry(alias, (Key)kp.getPrivate(), storePass.toCharArray(),
                        new Certificate[] {target});
}

まず、以下の行でキーペアを作成する。eTokenで使用可能なのはキーはRSAなのでそれを指定する。キー長は1024ビット(eToken PRO 32k/64k)もしくは2048ビット(eToken PRO 64k)を指定する。ただし、2048ビットを指定するには、eToken PRO 64kの場合でも2048ビットRSAキーを使用できるようにeTokenが初期化されている必要がある。

KeyPairGenerator kpgen = KeyPairGenerator.getInstance("RSA", provider);
kpgen.initialize(keyLength);
KeyPair kp = kpgen.generateKeyPair();

次に、生成したキーペアの公開鍵に自己証明書を作成し、秘密鍵で署名する。ここで指定しているprincipalには、「CN=Common Name,OU=Your OU,U=Your U,C=JP」のような文字列を指定する。自己証明のため、ISSUERとSUBJECTには同じ名前が入る。

Calendar cal = Calendar.getInstance();
Calendar expire = (Calendar)cal.clone();
expire.add(Calendar.DATE, 3650);
		
X509CertInfo info = new X509CertInfo();
		
CertificateValidity validity =
        new CertificateValidity(cal.getTime(), expire.getTime());
info.set(X509CertInfo.VALIDITY, validity);
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serial));

X500Name name = new X500Name(principal);
CertificateIssuerName issuer = new CertificateIssuerName(name);
CertificateSubjectName subject = new CertificateSubjectName(name);
AlgorithmId alogoId = AlgorithmId.get(
        AlgorithmId.sha1WithRSAEncryption_oid.toString());

info.set(X509CertInfo.ISSUER, issuer);
info.set(X509CertInfo.SUBJECT, subject);
info.set(X509CertInfo.KEY, new CertificateX509Key(kp.getPublic()));
info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(alogoId));

X509CertImpl target = new X509CertImpl(info);
target.sign(kp.getPrivate(), alogoId.getName(), provider.getName());

最後にこれらをkeyStore(eToken)にセーブする。

keyStore.setKeyEntry(alias, (Key)kp.getPrivate(), storePass.toCharArray(),
                    new Certificate[] {target});

実行すると、eTokenのランプがチカチカするのでよくわかる。