はじめに
このところ、ESP32のセキュリティ機能を調べていましたが、今回は他社ライブラリを載せてセキュリティ機能を実装する実験をしてみました。
使うのはwolfSSL社の暗号ライブラリ。SSLの他、様々な暗号処理やセキュリティ機能が提供されているようです。
SSLについてはESP-IDF自身でも実装できるので、S/MIMEなどで使われるPKCS#7 EnvelopedDataをESP32上で作ってみました。小さな組込みデバイスでこんなことができるなんて、ちょっと感動しました。
【今回の環境】
- ボード:ESP32-DevKitC-32D
- 開発環境:Windows 10 + ESP-IDF v4.0.1
- 追加ライブラリ:wolfSSL v4.5.0
ライブラリの入手とセットアップ
ライブラリは以下URLからダウンロード。
https://www.wolfssl.jp/download/
ESP-IDFで使う方法については以下に解説がありました。
https://www.wolfssl.com/docs/espressif/
まず、<wolfssl-root>\IDE\Espressif\ESP-IDF\setup.sh
を使って必要なファイルをコピーするのですが、自身のWindowsはbashを使える環境を用意してなかったので、同様の処理をするバッチファイルを作ってコピーしました。
if NOT EXIST "wolfcrypt" (
echo Move to wolfSSL top folder and retry. Aborted.
exit /B
)
set BASEDIR=%CD%
set WOLFSSL_ESPIDFDIR=%BASEDIR%\IDE\Espressif\ESP-IDF
set WOLFSSLLIB_TRG_DIR=%IDF_PATH%\components\wolfssl
set WOLFSSLEXP_TRG_DIR=%IDF_PATH%\examples\protocols
REM ===============================================
REM Remove/Create directories
rmdir /S/Q %WOLFSSLLIB_TRG_DIR%
mkdir %WOLFSSLLIB_TRG_DIR%
mkdir %WOLFSSLLIB_TRG_DIR%\src
mkdir %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src
mkdir %WOLFSSLLIB_TRG_DIR%\wolfssl
mkdir %WOLFSSLLIB_TRG_DIR%\test
mkdir %WOLFSSLLIB_TRG_DIR%\include
REM ===============================================
REM copying ... files in src/ into $WOLFSSLLIB_TRG_DIR/src
xcopy /F/Y %BASEDIR%\src\*.c %WOLFSSLLIB_TRG_DIR%\src\
xcopy /E/F/Y %BASEDIR%\wolfcrypt\src\*.c %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src\
xcopy /E/F/Y %BASEDIR%\wolfcrypt\src\*.i %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src\
xcopy /E/F/Y %BASEDIR%\wolfcrypt\src\port %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src\port\
xcopy /E/F/Y %BASEDIR%\wolfcrypt\test %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\
xcopy /E/F/Y %BASEDIR%\wolfcrypt\benchmark %WOLFSSLLIB_TRG_DIR%\wolfcrypt\benchmark\
xcopy /E/F/Y %BASEDIR%\wolfssl\*.h %WOLFSSLLIB_TRG_DIR%\wolfssl\
xcopy /E/F/Y %BASEDIR%\wolfssl\wolfcrypt %WOLFSSLLIB_TRG_DIR%\wolfssl\wolfcrypt\
REM ===============================================
REM user_settings.h
xcopy /F/Y %WOLFSSL_ESPIDFDIR%\user_settings.h %WOLFSSLLIB_TRG_DIR%\include\
copy /Y %WOLFSSL_ESPIDFDIR%\dummy_config_h %WOLFSSLLIB_TRG_DIR%\include\config.h
REM ===============================================
REM unit test app
xcopy /E/F/Y %WOLFSSL_ESPIDFDIR%\test %WOLFSSLLIB_TRG_DIR%\test\
copy /Y %WOLFSSL_ESPIDFDIR%\libs\CMakeLists.txt %WOLFSSLLIB_TRG_DIR%\
copy /Y %WOLFSSL_ESPIDFDIR%\libs\component.mk %WOLFSSLLIB_TRG_DIR%\
REM ===============================================
REM Benchmark program
rmdir /S/Q %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\
mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\main\
copy /Y %BASEDIR%\wolfcrypt\benchmark\benchmark.c %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\main\
xcopy /E/F/Y %WOLFSSL_ESPIDFDIR%\examples\wolfssl_benchmark %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\
REM ===============================================
REM Crypt Test program
rmdir /S/Q %WOLFSSLEXP_TRG_DIR%\wolfssl_test\
mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_test\main\
copy /Y %BASEDIR%\wolfcrypt\test\test.c %WOLFSSLEXP_TRG_DIR%\wolfssl_test\main\
xcopy /E/F/Y %WOLFSSL_ESPIDFDIR%\examples\wolfssl_test %WOLFSSLEXP_TRG_DIR%\wolfssl_test\
REM ===============================================
REM TLS Client program
rmdir /S/Q %WOLFSSLEXP_TRG_DIR%\wolfssl_client\
mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_client\main\include\
xcopy /E/F/Y %WOLFSSL_ESPIDFDIR%\examples\wolfssl_client %WOLFSSLEXP_TRG_DIR%\wolfssl_client\
REM ===============================================
REM TLS Server program
rmdir /S/Q %WOLFSSLEXP_TRG_DIR%\wolfssl_server\
mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_server\main\include\
xcopy /E/F/Y %WOLFSSL_ESPIDFDIR%\examples\wolfssl_server %WOLFSSLEXP_TRG_DIR%\wolfssl_server\
これによって、wolfSSLのソースコードがESP-IDFフォルダのcomponents\wolfssl
に、サンプルコードがexamples\protocols\wolfssl_*
にコピーされます。
続いて、コピー後のファイルcomponents\wolfssl\include\user_settings.h
に以下を追記。
#define WOLFSSL_ESPIDF
#define WOLFSSL_ESPWROOM32
サンプルのBenchmarkを動かしてみる
idf.py build
してみたところ、以下のwarningが多数発生
In file included from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h:45,
from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfssl/wolfcrypt/sha.h:73,
from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfssl/wolfcrypt/hash.h:35,
from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/md5.c:40:
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/esp32/include/rom/ets_sys.h:1:2: warning: #warning rom/ets_sys.h is deprecated, please use esp32/rom/ets_sys.h instead [-Wcpp]
#warning rom/ets_sys.h is deprecated, please use esp32/rom/ets_sys.h instead
原因はwolfSSLの以下のファイル。
components/wolfssl/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h
この中に以下の記述があります。
#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 1
#include <esp32/rom/ets_sys.h>
#else
#include <rom/ets_sys.h>
#endif
今回使ったESP-IDF v4.0.1では、ESP_IDF_VERSION_MAJOR=4
, ESP_IDF_VERSION_MINOR=0
が設定されます。なので<rom/ets_sys.h>
がincludeされるのですが、ESP-IDFとしては<esp32/rom/ets_sys.h>
を使って欲しいらしく、includeした<rom/ets_sys.h>
内のwarningが表示されたことによるもの。
そのため、wolfSSLのesp32-crypt.h
内の#if
行を以下のように修正。同じファイル内に同様の記述が他に2行あるので、合わせて修正。
#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 0
ビルドできたのでidf.py flash
したところ、こんな結果が出ました。ちゃんと動いているようです。
arg:-lng 0
------------------------------------------------------------------------------
wolfSSL version 4.5.0
------------------------------------------------------------------------------
wolfCrypt Benchmark (block bytes 1024, min 1.0 sec each)
RNG 1 MB took 1.011 seconds, 1.473 MB/s
AES-128-CBC-enc 6 MB took 1.004 seconds, 5.909 MB/s
AES-128-CBC-dec 5 MB took 1.004 seconds, 5.228 MB/s
AES-192-CBC-enc 6 MB took 1.000 seconds, 5.908 MB/s
AES-192-CBC-dec 5 MB took 1.000 seconds, 5.225 MB/s
AES-256-CBC-enc 6 MB took 1.001 seconds, 5.902 MB/s
AES-256-CBC-dec 5 MB took 1.001 seconds, 5.219 MB/s
AES-128-GCM-enc 375 KB took 1.006 seconds, 372.763 KB/s
AES-128-GCM-dec 375 KB took 1.006 seconds, 372.763 KB/s
AES-192-GCM-enc 375 KB took 1.021 seconds, 367.287 KB/s
AES-192-GCM-dec 375 KB took 1.021 seconds, 367.287 KB/s
AES-256-GCM-enc 375 KB took 1.029 seconds, 364.431 KB/s
AES-256-GCM-dec 375 KB took 1.029 seconds, 364.431 KB/s
ARC4 8 MB took 1.001 seconds, 7.561 MB/s
RABBIT 5 MB took 1.002 seconds, 5.385 MB/s
3DES 450 KB took 1.031 seconds, 436.469 KB/s
MD5 14 MB took 1.001 seconds, 13.756 MB/s
SHA 14 MB took 1.000 seconds, 14.478 MB/s
SHA-256 14 MB took 1.001 seconds, 14.366 MB/s
SHA-512 16 MB took 1.000 seconds, 16.479 MB/s
HMAC-MD5 14 MB took 1.001 seconds, 13.609 MB/s
HMAC-SHA 14 MB took 1.000 seconds, 14.209 MB/s
HMAC-SHA256 14 MB took 1.001 seconds, 14.097 MB/s
HMAC-SHA512 16 MB took 1.000 seconds, 15.942 MB/s
PBKDF2 704 bytes took 1.044 seconds, 674.330 bytes/s
RSA 2048 public 52 ops took 1.005 sec, avg 19.327 ms, 51.741 ops/sec
RSA 2048 private 4 ops took 1.054 sec, avg 263.500 ms, 3.795 ops/sec
ECC 256 key gen 4 ops took 1.262 sec, avg 315.500 ms, 3.170 ops/sec
ECDHE 256 agree 4 ops took 1.260 sec, avg 315.000 ms, 3.175 ops/sec
ECDSA 256 sign 4 ops took 1.273 sec, avg 318.250 ms, 3.142 ops/sec
ECDSA 256 verify 2 ops took 1.220 sec, avg 610.000 ms, 1.639 ops/sec
CURVE 25519 key gen 3 ops took 1.279 sec, avg 426.333 ms, 2.346 ops/sec
CURVE 25519 agree 4 ops took 1.702 sec, avg 425.500 ms, 2.350 ops/sec
ED 25519 key gen 47 ops took 1.013 sec, avg 21.553 ms, 46.397 ops/sec
ED 25519 sign 42 ops took 1.018 sec, avg 24.238 ms, 41.257 ops/sec
ED 25519 verify 26 ops took 1.008 sec, avg 38.769 ms, 25.794 ops/sec
Benchmark complete
PKCS#7 EnvelopedDataを作ってみる
プログラム
wolfSSLのマニュアルはこちらにありますが、
wolfSSL Manual
API Referenceは記述が少なかったり内容が古かったりするようで、あまり参考にならず。
なので、githubにあるサンプルプログラムを参考にしました。
wolfSSL Example Applications
EnvelopedDataでくるむ中身は、以前に作った温度センサの値を取得するプログラムを流用してその値を使います。
ESP32で温度と湿度をAWS IoTへ送ってグラフ化してみた
本当は、S/MIMEフォーマットにしてメールで送れたりすると良かったのですが、SMTP周りのコードを書くのが面倒だったので、ESP-IDF付属のサンプルを使ってHTTPでダウンロードする形にしました。
以下は、PKCS#7 EnvelopedDataを作るところと、できたファイルをHTTP Responseで返す部分。これをESP-IDF付属のサンプルexamples\protocols\http_server\simple
に組み込みました。
#include "wolfssl/wolfcrypt/pkcs7.h"
extern const uint8_t testcert_der_start[] asm("_binary_testcert_der_start");
extern const uint8_t testcert_der_end[] asm("_binary_testcert_der_end");
static byte pkcs_der[3000];
static int encodeEnvelopedData(char* msg, byte* out, word32 outSz)
{
int ret;
PKCS7* pkcs7;
RNG rng;
ret = wc_InitRng(&rng);
if (ret != 0){
printf("wc_InitRng() failed, ret = %d\n", ret);
return -1;
}
pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID);
if (pkcs7 == NULL) {
printf("wc_PKCS7_New() failed\n");
return -1;
}
pkcs7->rng = &rng;
pkcs7->content = (byte*)msg;
pkcs7->contentSz = strlen(msg);
pkcs7->contentOID = DATA;
pkcs7->encryptOID = AES256CBCb;
/* add recipient using RSA certificate (KTRI type) */
ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, testcert_der_start,
(testcert_der_end - testcert_der_start), 0);
if (ret < 0) {
printf("wc_PKCS7_AddRecipient_KTRI() failed, ret = %d\n", ret);
wc_PKCS7_Free(pkcs7);
return -1;
}
/* encode EnvelopedData, returns size */
ret = wc_PKCS7_EncodeEnvelopedData(pkcs7, out, outSz);
if (ret <= 0) {
printf("ERROR: wc_PKCS7_EncodeEnvelopedData() failed, ret = %d\n", ret);
wc_PKCS7_Free(pkcs7);
return -1;
} else {
printf("Successfully encoded EnvelopedData bundle\n");
}
wc_PKCS7_Free(pkcs7);
return ret;
}
/* An HTTP GET handler */
static esp_err_t enveloped_get_handler(httpd_req_t *req)
{
int dataSz;
char msg[100];
sprintf(msg, "Temperature: %.2f, Humidity: %.2f", readTemp(), readHumid());
if (0 >= (dataSz = encodeEnvelopedData(msg, pkcs_der, sizeof(pkcs_der)))) {
return ESP_FAIL;
}
httpd_resp_set_hdr(req, "Content-Type", "binary/octet-stream");
httpd_resp_set_hdr(req, "Content-Disposition", "attachment; filename=test.p7m");
httpd_resp_send(req, (char*)pkcs_der, dataSz);
if (httpd_req_get_hdr_value_len(req, "Host") == 0) {
ESP_LOGI(TAG, "Request headers lost");
}
return ESP_OK;
}
static const httpd_uri_t enveloped = {
.uri = "/enveloped",
.method = HTTP_GET,
.handler = enveloped_get_handler,
};
EnvelopedDataを作る際のRecipient証明書は、OpenSSLで適当に作成。プロジェクトフォルダのcerts/testcert.der
にDER形式で保存。対応するPrivate Keyは後で使います。
CMakefile.txt
内のidf_component_register
にEMBED_FILES ${project_dir}/certs/testcert.der
を追加して、アプリに組み込みます。
また、PKCS#7を使う際はHAVE_PKCS7
および関連する値をdefineしておく必要があるそうなので、CMakeList.txt
に以下を追記します(これをしておかないと、必要関数がコンパイルされずリンク時にエラーになる)。
add_compile_options(-DHAVE_PKCS7)
add_compile_options(-DHAVE_AES_KEYWRAP)
add_compile_options(-DHAVE_X963_KDF)
add_compile_options(-DWOLFSSL_AES_DIRECT)
ビルド
すんなりとは行かず、wolfSSLのソースをいくつか修正しました。以下、正しい対処方法なのかわかりませんが、記録として載せておきます。
snprintfでコンパイルエラー
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c: In function 'GetAsnTimeString':
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c:6261:23: error: '%02d' directive output may be truncated writing between 2 and 11 bytes into a region of size between 5 and 12 [-Werror=format-truncation=]
"%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
^~~~
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c:6261:19: note: directive argument in the range [-2147483647, 2147483647]
"%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfssl/wolfcrypt/asn.h:37,
from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c:68:
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfssl/wolfcrypt/types.h:497:31: note: 'snprintf' output between 16 and 68 bytes into a destination of size 16
#define XSNPRINTF snprintf
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c:6260:9: note: in expansion of macro 'XSNPRINTF'
XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE,
^~~~~~~~~
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c:6240:28: error: '%02d' directive output may be truncated writing between 2 and 11 bytes into a region of size between 0 and 10 [-Werror=format-truncation=]
"%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
^~~~
In file included from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfssl/wolfcrypt/asn.h:37,
from C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c:68:
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfssl/wolfcrypt/types.h:497:31: note: 'snprintf' output between 14 and 60 bytes into a destination of size 14
#define XSNPRINTF snprintf
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/asn.c:6239:9: note: in expansion of macro 'XSNPRINTF'
XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE,
^~~~~~~~~
-Wno-error=format-truncation=
では解消しなかったので、ソースを直接修正(snprintfの書込み先サイズを拡張)。
int GetAsnTimeString(void* currTime, byte* buf, word32 len)
{
/* (snip) */
char utc_str[ASN_UTC_TIME_SIZE+16];
/* (snip) */
XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE+16,
"%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
/* (snip) */
char gt_str[ASN_GENERALIZED_TIME_SIZE+16];
/* (snip) */
XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE+16,
"%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
/* (snip) */
}
変数の初期化漏れエラー
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/pkcs7.c: In function 'wc_PKCS7_DecodeEncryptedData':
C:/IoT/ESP-IDF/ESP-IDF-v4.0.1/components/wolfssl/wolfcrypt/src/pkcs7.c:12206:42: error: 'padLen' may be used uninitialized in this function [-Werror=maybe-uninitialized]
ret = encryptedContentSz - padLen;
~~~~~~~~~~~~~~~~~~~^~~~~~~~
-Wno-error=maybe-uninitialized
では解消しなかったので、ソースを直接修正(変数宣言時に初期化、2ヶ所)。
byte padLen = 0;
PKCS#7 encoding実験
ビルドできたのでidf.py flash
で書込み。
idf.py monitor
にてMSP32のIPを確認。
I (10142) tcpip_adapter: sta ip: 192.168.0.8, mask: 255.255.255.0, gw: 192.168.0.1
I (10142) example_connect: Connected to <SSID>
I (10142) example_connect: IPv4 address: 192.168.0.8
I (10152) example: Starting server on port: '80'
I (10162) example: Registering URI handlers
PCのブラウザでhttp://192.168.0.8/enveloped
に接続すると、test.p7m
がダウンロードされました。
まずは、OpenSSL
のasn1parse
コマンドでデータ構造を確認。ちゃんとPKCS#7 EnvelopedDataになっているようです。もちろんデータはAES 256bitで暗号化されているので読めません。
> openssl.exe asn1parse -i -inform DER -in test.p7m
0:d=0 hl=4 l= 508 cons: SEQUENCE
4:d=1 hl=2 l= 9 prim: OBJECT :pkcs7-envelopedData
15:d=1 hl=4 l= 493 cons: cont [ 0 ]
19:d=2 hl=4 l= 489 cons: SEQUENCE
23:d=3 hl=2 l= 1 prim: INTEGER :00
26:d=3 hl=4 l= 388 cons: SET
30:d=4 hl=4 l= 384 cons: SEQUENCE
34:d=5 hl=2 l= 1 prim: INTEGER :00
37:d=5 hl=2 l= 104 cons: SEQUENCE
39:d=6 hl=2 l= 99 cons: SEQUENCE
41:d=7 hl=2 l= 11 cons: SET
43:d=8 hl=2 l= 9 cons: SEQUENCE
45:d=9 hl=2 l= 3 prim: OBJECT :countryName
50:d=9 hl=2 l= 2 prim: PRINTABLESTRING :JP
54:d=7 hl=2 l= 26 cons: SET
56:d=8 hl=2 l= 24 cons: SEQUENCE
58:d=9 hl=2 l= 3 prim: OBJECT :organizationName
63:d=9 hl=2 l= 17 prim: UTF8STRING :Test Organization
82:d=7 hl=2 l= 33 cons: SET
84:d=8 hl=2 l= 31 cons: SEQUENCE
86:d=9 hl=2 l= 3 prim: OBJECT :organizationalUnitName
91:d=9 hl=2 l= 24 prim: UTF8STRING :Test Organizational Unit
117:d=7 hl=2 l= 21 cons: SET
119:d=8 hl=2 l= 19 cons: SEQUENCE
121:d=9 hl=2 l= 3 prim: OBJECT :commonName
126:d=9 hl=2 l= 12 prim: UTF8STRING :Test Root CA
140:d=6 hl=2 l= 1 prim: INTEGER :07
143:d=5 hl=2 l= 13 cons: SEQUENCE
145:d=6 hl=2 l= 9 prim: OBJECT :rsaEncryption
156:d=6 hl=2 l= 0 prim: NULL
158:d=5 hl=4 l= 256 prim: OCTET STRING [HEX DUMP]:8AD2004F298A004CE9981C21F6D7EF0289A98D7963706AA28E65A25A6990BAB2440210CCE3B7D063694C9A898BF36D657A4BB16D73460E267F12EEB1AEB4CA60D6DFA8CD407C584F33EB7D1F5B89326A1A7078015A5A17EDAC08E0BEACFEF236F14AF6AFE0701F2009CEB1AD897FD783659D7A426A8E1A691A77B1F0981379E4CBD71563782572643BA42511B990A9AB45EAF4ADC3047770CC96D34C50D1E93BA04FC7117E6AE825BB83276AF33B1218A404672916D052E58F66FD36412D812F39845E794BAA349A853CED5DA4CE35EBEC7CD4E9FF737443DFBB2F336790439F5B091919495468CA9C6F680F9283C83DF755879498059AE70A6481F6BCC6AF39
418:d=3 hl=2 l= 92 cons: SEQUENCE
420:d=4 hl=2 l= 9 prim: OBJECT :pkcs7-data
431:d=4 hl=2 l= 29 cons: SEQUENCE
433:d=5 hl=2 l= 9 prim: OBJECT :aes-256-cbc
444:d=5 hl=2 l= 16 prim: OCTET STRING [HEX DUMP]:26FADBEA4DC07CD294062AB03ED6F99B
462:d=4 hl=2 l= 48 prim: cont [ 0 ]
次に、OpenSSL
のSMIME
コマンドで中を見てみます。
> openssl.exe smime -decrypt -inform DER -in test.p7m -recip testcert.cer -inkey testcert.key
Temperature: 30.34, Humidity: 52.28
復号して中を見ることができました!
ちゃんと機能しているようです。このライブラリがあればいろいろなデバイスで暗号処理できそうです。