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

執筆者:

関連記事

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

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

nvm-windows1.1.6でNode.jsを入れようとするとnpmコマンドのインストールがエラーになる

目次1 事象2 原因3 対処4 まとめ 事象 Win10、nvm-windows 1.1.6環境下でNode.js 10.16.0を入れようとした際に以下のエラーが発生。 C:\src\js\angu …

ローカルネットワーク内のHTTP通信が2回に1回交互にタイムアウトするようになった原因

目次1 事象2 調査3 解決4 その後 事象 ある日突然、オフィスのローカル開発環境でHTTP通信が異常なほど遅くなり、タイムアウトするようになりました。 その後F5でリロードすると普通にレスポンスが …

Apple PayのMerchant Doamin設定がPendingになり、Verifiedにならなかった原因

開発しているWebシステム上でApple Payによるクレジットカード選択が出来るようにするには「Apple Developer Program」で「Merchant Domain」を設定します。 O …

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

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

 

shingo.nakanishi
 

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