茱萸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】【Python】virtualenvを使う

UbuntuでPythonのパッケージ管理をしやすくするためにvirtualenvを導入します。

Raspberry Pi で Windows PC をシャットダウン or スリープモードにする

Windows PC を Raspberry Pi から遠隔操作してシャットダウン or スリープモードにします。

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

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

LPC11U35を汎用ARMデバッガとして使う

秋月で売っているLPC11U35を汎用ARMデバッガとして使いたいと思います。

AVR32を使う

Atmel製のマイコン「AVR32」を使ってみた感想です。