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
-,

執筆者:

関連記事

スタンドアロンモードのPgAdmin4が開くデフォルトブラウザを変更

PostgreSQL公式GUIクライアントツールの「PgAdmin4」。 PostGISのgeometry型をWeb地図上に表示出来たり、サーバモードで起動すればチーム内で共通的に使えるPostgre …

キャッシュされているはずのServiceWorker資源にオフラインアクセス出来ない(Workbox + ionicons)

そのHTTPリクエストしたファイル資源、ひょっとしてURLパラメータついてたりしませんか? 目次1 事象2 原因3 対処 事象 ionic3(SPA)でWorkboxを使ったServiceWorker …

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

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

adb devicesコマンドでAndroid端末を認識しない

目次1 事象2 原因3 解決 事象 USB接続するAndroidによって以下のエラーが出たりします。 C:\src\ionic\awsomeapp>adb devices List of dev …

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

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

 

shingo.nakanishi
 

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