茱萸note

電子工作の備忘録と旅行の記録

Arduino ESP8266 IoT マイコン 電子工作

ESP8266 で RSA PKCS#1 V1.5 暗号の復号

投稿日:

ESP8266 で RSA 暗号化の方式の一つである RSA PKCS#1 V1.5 、別名 RSAES-PKCS1-v1_5 の暗号を復号する方法です。


目次


別記事で、AES-CBC PKCS#7 Padding の暗号化・復号を ESP8266 で実現しました。

今回は、RSA 暗号化の方式の一つである RSA PKCS#1 V1.5 、別名 RSAES-PKCS1-v1_5 の暗号の復号を ESP8266 で試します。前回同様、ESP8266 の SDK に付属している BearSSL を利用して実装します。

RSA 暗号化の2つの方式

RSA アルゴリズムでの暗号化には2つの方式があります。

後者の RSAES-PKCS1-v1_5 は古い方式とされており、前者の RSAES-OAEP 方式が推奨されています。しかしこの度、RSAES-PKCS1-v1_5 の復号を実装する機会があったので、その方法を簡単に紹介する運びとなりました。

PKCS#1 V1.5 の名が付くスキームは、他にも RSASSA-PKCS1-v1_5EMSA-PKCS1-v1_5 がありますが、これらは証明書の署名に関するスキームであり、今回扱う暗号化スキーム RSAES-PKCS1-v1_5 とは異なります。

RSA PKCS1 V1.5 暗号の復号

先にプログラムを示します。このプログラムは事前に公開鍵を送信したサーバーから暗号文が届き、それを秘密鍵で復号するという想定で書いています。

const char rsa_private_key[] = R"EOF(
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
)EOF";

const char rsa_public_key[] = R"EOF(
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
)EOF";

// Input : data
uint8_t data[] = {...};
int len = sizeof(data);

// RSA PKCS#1 V1.5 Decryption
BearSSL::PrivateKey *private_key = new BearSSL::PrivateKey(rsa_private_key);

(*br_rsa_private_get_default())(data, private_key->getRSA());

int i;
for(i = 2; i < len; i++){
  if(data[i] == 0) break;
}
i++;

len -= i;
uint8_t decoded_data[len];
memcpy(decoded_data, &data[i], len);

// Output : Decoded data
// return decoded_data;

プログラムの説明

鍵を PEM 形式で書きます。ESP8266 に鍵のペアを生成させるのは難しい気がするので、鍵の生成は openssl などで事前に済ませておきます。

const char rsa_private_key[] = R"EOF(
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
)EOF";

鍵は ESP8266 Arduino ライブラリの BearSSL::PrivateKey クラスにブチ込みます。

BearSSL::PrivateKey *private_key = new BearSSL::PrivateKey(rsa_private_key);

暗号は次で復号します。復号文は暗号を格納していた data に書かれます。

(*br_rsa_private_get_default())(data, private_key->getRSA());

次は、PKCS#1 V1.5 Padding の処理です。復号文から元の平文を抽出します。

RSAES-PKCS1-v1_5 では、復号文は 00 02 から始まります。そして、平文は、次に 00 が現れたらその次のバイトから始まります。要するに、復号文は 00 02 <ゴミ(00を含まない)> 00 <平文> という形式になっています。

int i;
for(i = 2; i < len; i++){
  if(data[i] == 0) break;
}
i++;

len -= i;
uint8_t decoded_data[len];
memcpy(decoded_data, &data[i], len);

-電子工作
-, , , ,


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

【Ubuntu】【上級者向け】EFIシステムパーティションを作成する

「空っぽのSSD・HDD・USBメモリにUbuntuをインストールしたい!」といった人に向けて、空っぽのSSD・HDD・USBメモリにEFIシステムパーティションを作成する方法を説明します。

【上級者向け】Ubuntuをデュアルブートする《その1:既にWindowsが入っているSSD・HDDにUbuntuを入れる》

既にWindowsがインストールされているSSD・HDDに追加でUbuntuをインストールする方法です。上級者向け。

【Ubuntu】【上級者向け】Grubブートローダを削除する

「デュアルブートしてたけどUbuntuを削除することにした。」という人などに向けて、Grubブートローダ(Ubuntuのブートローダ)を削除する方法を説明します。

Tp-Link のスマートプラグ『Tapo P105』を PC・Raspberry Pi から直接操作する

Tp-Link のスマートプラグ『Tapo P105』をアプリや IFTTT といった外部サービスを用いずに、PC・Raspberry Pi から直接操作してみます。

Visual Studio 2019でC言語のお勉強を始める

Visual Studio 2019 で C言語 のお勉強をする人に向けて書きます。