Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第36章. バイトコードと署名付きバイトコードの読み込み

この章の目的

この章を読み終える頃には、事前にコンパイルされたバイトコードを読み込み、信頼マトリクスに対して署名付きバイトコードを読み込み、そしてトラストスキップコンストラクタを理解しているはずです。この章を読み終える頃には、事前にコンパイルされたバイトコードを読み込み、信頼マトリクスに対して署名付きバイトコードを読み込み、そしてトラストスキップコンストラクタを理解しているはずです。

事前にコンパイルされたバイトコードを読み込む

keleusma compileやビルドパイプラインから出てきた.kel.binファイルをホストが持っている場合、字句解析、構文解析、コンパイルの各段階を飛ばせます。keleusma compileやビルドパイプラインから出てきた.kel.binファイルをホストが持っている場合、字句解析、構文解析、コンパイルの各段階を飛ばせます。

#![allow(unused)]
fn main() {
let bytes  = std::fs::read("script.kel.bin")?;
let mut vm = Vm::load_bytes(&bytes, &arena)?;
}

Vm::load_bytesはワイヤフォーマットのフレーミングを検証し、構造検証を行い、資源境界検証を行って、VMを返します。フレーミングの失敗はVmError::LoadError、解析の失敗はVmError::VerifyErrorです。検証はソースからコンパイルされたモジュールに対するものと同じです。バイトコードの読み込みは安全性のチェックを飛ばすわけではなく、コンパイルを飛ばすだけです。Vm::load_bytesはワイヤフォーマットのフレーミングを検証し、構造検証を行い、資源境界検証を行って、VMを返します。フレーミングの失敗はVmError::LoadError、解析の失敗はVmError::VerifyErrorです。検証はソースからコンパイルされたモジュールに対するものと同じです。バイトコードの読み込みは安全性のチェックを飛ばすわけではなく、コンパイルを飛ばすだけです。

署名付きバイトコードを読み込む

signedのエントリー関数からコンパイルされたモジュールはFLAG_REQUIRES_SIGNATUREビットを運び、Vm::load_bytesはそれを拒否して、署名付きの経路に呼び出し側を案内します。署名付きモジュールはVm::load_signed_bytesで読み込みます。これは信頼する公開鍵のスライスを取ります。signedのエントリー関数からコンパイルされたモジュールはFLAG_REQUIRES_SIGNATUREビットを運び、Vm::load_bytesはそれを拒否して、署名付きの経路に呼び出し側を案内します。署名付きモジュールはVm::load_signed_bytesで読み込みます。これは信頼する公開鍵のスライスを取ります。

#![allow(unused)]
fn main() {
let pub_bytes: [u8; 32] = std::fs::read("pub.bin")?.try_into().unwrap();
let key = ed25519_dalek::VerifyingKey::from_bytes(&pub_bytes)?;
let mut vm = Vm::load_signed_bytes(&signed_bytes, &arena, &[key])?;
}

このスライスが信頼マトリクスです。モジュールは、署名がスライス内のどれかの鍵に対して通れば読み込まれます。空のスライスはすべての署名付きモジュールを拒否します。マトリクスは構築されたVMにコピーされるので、その後の署名付きホットスワップ読み込みも同じ鍵を継承します。このスライスが信頼マトリクスです。モジュールは、署名がスライス内のどれかの鍵に対して通れば読み込まれます。空のスライスはすべての署名付きモジュールを拒否します。マトリクスは構築されたVMにコピーされるので、その後の署名付きホットスワップ読み込みも同じ鍵を継承します。

署名されていないベースラインから起動して、その後だけ署名付きの更新を受け入れるホストは、構築のあとに鍵を登録します。署名されていないベースラインから起動して、その後だけ署名付きの更新を受け入れるホストは、構築のあとに鍵を登録します。

#![allow(unused)]
fn main() {
let mut vm = Vm::new(unsigned_baseline_module, &arena)?;
vm.register_verifying_key(operator_key);
}

トラストスキップコンストラクタ

Vm::new_uncheckedは資源境界検証を飛ばします。実行ループはメモリ安全のために構造検証に依存しているので、構造検証は依然として走ります。Vm::new_uncheckedは資源境界検証を飛ばします。実行ループはメモリ安全のために構造検証に依存しているので、構造検証は依然として走ります。

#![allow(unused)]
fn main() {
let vm = unsafe { Vm::new_unchecked(module, &arena) };
}

unsafeが付いているのは信頼契約を表すためです — 呼び出し側は、バイトコードの資源境界が以前にビルド時に検証されたことを誓います。意図される用途は、1回検証してバイトコードを配布し、毎回の読み込みで再検証しなくて済むビルドパイプラインです。安全な検証器が却下するプログラムを通すために使うのは、言語の保証の外側での意図的な誤用で、そう文書化されています。第5部の有界な時間とメモリの保証は、Vm::newの下では成り立ち、Vm::new_uncheckedの下ではホストの誓いに弱まります。unsafeが付いているのは信頼契約を表すためです — 呼び出し側は、バイトコードの資源境界が以前にビルド時に検証されたことを誓います。意図される用途は、1回検証してバイトコードを配布し、毎回の読み込みで再検証しなくて済むビルドパイプラインです。安全な検証器が却下するプログラムを通すために使うのは、言語の保証の外側での意図的な誤用で、そう文書化されています。第5部の有界な時間とメモリの保証は、Vm::newの下では成り立ち、Vm::new_uncheckedの下ではホストの誓いに弱まります。

この章のまとめ

  • Vm::load_bytesは事前にコンパイルされた.kel.binを読み込み、ソースからコンパイルされたモジュールと同じく検証します。Vm::load_bytesは事前にコンパイルされた.kel.binを読み込み、ソースからコンパイルされたモジュールと同じく検証します。
  • Vm::load_signed_bytesは信頼する公開鍵のスライスに対して署名付きバイトコードを読み込みます。Vm::load_signed_bytesは信頼する公開鍵のスライスに対して署名付きバイトコードを読み込みます。
  • register_verifying_keyは構築後のVMに鍵を加えます。
  • Vm::new_uncheckedは、明示的なunsafeの信頼契約のもとで、資源境界チェックを飛ばします。Vm::new_uncheckedは、明示的なunsafeの信頼契約のもとで、資源境界チェックを飛ばします。

次の章では走っているモジュールを新しいものに置き換えます。