trouble shooting

java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=111, too big.

投稿日:2019年6月22日

事象

OpenSSLで作成した秘密鍵をJava(Eclipse + Maven環境)で読み込み、公開鍵で暗号化されたデータを復号しようとした際に例外が発生しました。

秘密鍵ファイルは以下のように作成しています。

// 秘密鍵作成
$ openssl genrsa -out rsa_2048_priv.pem 2048

// 秘密鍵をPEMからPKCS#8のDERフォーマットに変換
$ openssl pkcs8 -in rsa_2048_priv.pem -topk8 -nocrypt -outform DER -out rsa_2048_priv.der

クラスパス直下(Maven的にはsrc/main/resources)に秘密鍵ファイル(rsa_2048_priv.der)を置いておき、ClassLoader.getResourceAsStream()で読み込んでPrivateKeyインスタンスを作ります。

    // 鍵ファイル内容のバイト配列を作成
    InputStream in = 
        this.getClass().getClassLoader().getResourceAsStream("rsa_2048_priv.der");
    byte[] buff = new byte[in.available()];
    in.read(buff);

    // 秘密鍵インスタンス生成
    KeySpec keyspec = new PKCS8EncodedKeySpec(buff);  <-- 以下のエラーが発生する

    KeyFactory keyfactory = KeyFactory.getInstance( "RSA");
    Key privateKey = keyfactory.generatePrivate(keyspec);
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);

すると例外が発生。

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=111, too big.
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
    at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)

    (snip)

原因

原因究明の為、試しにsrc/main/resourcesに置いた鍵ファイルを実行ディレクトリ直下に置いてクラスパスではなくファイルパスで読み込むとエラー無く成功します。

原因は環境別ビルドの為に行っているMavenのリソースフィルタリングの際、resources配下の全ファイルにUTF-8変換が走る設定をしていた為でした。

src/main/resources内のファイルをclassesにコピーする際、propertiesはUTF-8にして貰っていいですが、バイナリまで対象になっていて結果鍵ファイルが壊れ、KeySpecクラスインスタンスの生成に失敗していました。

対処

pom.xmlでバイナリファイルはリソースフィルタリングの対象から外し、単純にclassesにコピーだけして貰います。

Maven Resources Pluginのドキュメントに方法が載っています。

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <!-- .derファイルはフィルタリングしない設定を追加 -->
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>der</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
            </plugin>

これでUTF-8変換が走らず、OpenSSLで作られたままのバイナリファイルとしてclassesにコピーされ、インスタンス化に成功しました。

得た教訓

Mavenリソースフィルタリングしている場合、/src/main/resourcesにバイナリを置く時は要注意。

-trouble shooting
-,

執筆者:

関連記事

EclipseのXMLエディタ一行目でDTDエラー「参照ファイルにエラーが含まれています」

目次1 事象2 原因3 対処4 まとめ 事象 checkstyleのルールXMLをEclipseで開くと一行目にエラーマーク。 カーソルを合わせた時のメッセージ。 XMLのデータ構造整合性をチェックす …

Angular4.4のHTTP通信処理にタイムアウトを設定をすると「timeout is not a function」エラーが発生する

目次1 事象2 原因3 対処4 まとめ 事象 Angular4.3で追加されたHttpClientModuleに移行せず、HttpModuleを使い続けているアプリで、とある理由からpackage-l …

Metabaseの登録データベース削除時に入力を求められて消せない

分析対象として登録したデータベースを一覧から削除する際に入力値を求められ、何を入れていいか分からずプチはまりました。 結論から述べると入力する文字は「delete」でした。 事象 Metabase(v …

Angular11から12にアップデートしたらng serveがproductionモードで起動するようになってしまう

既存のAngular11のプロジェクトを12に上げた際に発生。 目次1 環境2 事象3 原因4 対処5 根本原因6 まとめ 環境 Windows 11Node.js 14.15.1Angular13リ …

Angularのテンプレート評価式にビット演算を使うとTemplate parse errorが発生する

AngularのテンプレートHTMLでビット演算をすることは禁じられているので代替手段を考えます。 目次1 事象2 原因3 対処 事象 CSSクラスをビット演算で切り替えるテンプレートを書きました。c …

 

shingo.nakanishi
 

東京在勤、1977年生まれ、IT職歴2n年、生涯技術者として楽しく生きることを目指しています。デスマに負けず健康第一。