対称鍵を生成しよう
🔑 対称鍵を生成しよう
前回のレッスンでバックエンドキャニスターを更新したので、改めてデプロイを行いましょう。
dfx start --clean --background
npm run deploy:local
npm run start
ここからは、encrypted_notes_frontend/内のファイルを更新していきます。
まずは、cryptoService.tsファイルを更新しましょう。インタフェースに定義した型をクラス内で使用したいのでインポートします。
import {
_SERVICE,
Result_1,
} from '../../../declarations/encrypted_notes_backend/encrypted_notes_backend.did';
init関数に対称鍵の生成と登録を行うコードを追加します。/** STEP9: 対称鍵を生成します。 */の下を下記のコードで更新しましょう。
/** STEP9: 対称鍵を生成します。 */
// 対称鍵が生成されているかどうかを確認します。
const isSymKeyRegistered =
await this.actor.isEncryptedSymmetricKeyRegistered();
if (!isSymKeyRegistered) {
console.log('Generate symmetric key...');
// 対称鍵を生成します。
this.symmetricKey = await this.generateSymmetricKey();
// 対称鍵を公開鍵で暗号化します。
const wrappedSymmetricKeyBase64: string = await this.wrapSymmetricKey(
this.symmetricKey,
this.publicKey,
);
// 暗号化した対称鍵をバックエンドキャニスターに登録します。
const result: Result_1 =
await this.actor.registerEncryptedSymmetricKey(
this.exportedPublicKeyBase64,
wrappedSymmetricKeyBase64,
);
if ('Err' in result) {
if ('UnknownPublicKey' in result.Err) {
throw new Error('Unknown public key');
}
if ('AlreadyRegistered' in result.Err) {
throw new Error('Already registered');
}
if ('DeviceNotRegistered' in result.Err) {
throw new Error('Device not registered');
}
}
/** STEP10: 対称鍵を同期します。 */
return true;
} else {
/** STEP11: 対称鍵を取得します。 */
return false;
}
}
追加したコードを確認していきましょう。
まず、isEncryptedSymmetricKeyRegistered関数を呼び出して、対称鍵が登録されているかを確認します。登録されていない場合は対称鍵を生成し、既に登録されている場合は何もせずに、今はfalseを返して終了します。
const isSymKeyRegistered =
await this.actor.isEncryptedSymmetricKeyRegistered();
if (!isSymKeyRegistered) {
console.log('Generate symmetric key...');
...
return true;
} else {
return false;
}
対称鍵の生成は、private関数として定義されているgenerateSymmetricKey関数で行います 。内部でどのような処理を行なっているか目を通してみてください。生成した対称鍵はそのまま扱わずに、先に生成している公開鍵で暗号化します。対称鍵の暗号化もprivate関数として既に定義されているwrapSymmetricKey関数で行います。
// 対称鍵を生成します。
this.symmetricKey = await this.generateSymmetricKey();
// 対称鍵を公開鍵で暗号化します。
const wrappedSymmetricKeyBase64: string = await this.wrapSymmetricKey(
this.symmetricKey,
this.publicKey,
);
wrapSymmetricKey関数を簡単に解説します。鍵を暗号化するには、SubtleCryptoオブジェクト のwrapKeyメソッドを使用します。wrapKeyメソッドは、暗号化する鍵の種類によって引数の指定方法が異なります。今回は対称鍵を暗号化するので、第一引数(format)にはraw、第二引数(key)にはラップしたい鍵:対称鍵、第三引数(wrappingKey)には暗号化に使用する鍵:公開鍵、第四引数(wrapAlgo)には暗号化アルゴリズムRSA-OAEPを指定します。
// lib/cryptoService.ts, wrapSymmetricKey()
const wrappedSymmetricKey = await window.crypto.subtle.wrapKey(
'raw',
symmetricKey,
wrappingKey,
{
name: 'RSA-OAEP',
},
);
init関数に戻り、最後は暗号化された対称鍵をバックエンドキャニスターに登録します。登録時にエラーが返され たら、対応するエラーをスローします。
const result: Result_1 =
await this.actor.registerEncryptedSymmetricKey(
this.exportedPublicKeyBase64,
wrappedSymmetricKeyBase64,
);
if ('Err' in result) {
if ('UnknownPublicKey' in result.Err) {
throw new Error('Unknown public key');
}
if ('AlreadyRegistered' in result.Err) {
throw new Error('Already registered');
}
if ('DeviceNotRegistered' in result.Err) {
throw new Error('Device not registered');
}
}
ここまでで、対称鍵の生成を行うコードが実装できました。