タラバガニー設計局stalins.clubNOTE/notes/input-addressed-vs-content-addressed

Nixのstore pathは通常content-addressedではない

Nixのstore pathにはhashが含まれるため、「/nix/store/<hash>-name はartifact内容のhashだ」と理解されやすい。しかし通常のNix store pathはそうではない。Nix 2.35の公式マニュアルは、通常のstore pathを input-addressed と説明している。

Nixのsubstituteは「バイナリパッケージ」よりbuild resultに近い を理解するうえで、この区別は重要である。

input-addressed pathでは、hash部分はoutputのbytesそのものではなく、derivationの内容、すなわちbuild-time dependency graphなどの入力側の情報から決まる。したがって同じstore pathを名乗るobjectを外部binary cacheから受け取っただけでは、「そのbytesが期待したderivationから本当に生成された」ことをpathだけで検証できない。このためNixはinput-addressed objectを別storeからimportするときtrusted keyによる署名を要求する。

対してcontent-addressed store objectでは、pathのdigestはそのstore objectのfile-system object graph、references、store directory、nameといったobject固有の情報から計算される。取得した内容からaddressを再計算できるため、Nixのnix store make-content-addressedの説明では、content-addressed pathは追加の署名なしでも内容を検証できるとしている。

ここから「hash」と「trust」の関係が見えてくる。

  • input-addressed: addressは「このbuild inputから作られるはずのobject」というidentityを表す。外部から受け取るactual bytesがそのbuild resultであることは別途trustが必要になる。
  • content-addressed: address自体がactual contentに結び付くため、少なくとも「期待したcontent addressと一致するbytesか」は自己検証できる。

ただしcontent-addressedだから安全なsoftwareだという意味ではない。悪意あるartifactにも一意なcontent addressは付く。誰が、どのsourceから、どのbuilderで作ったかという問いは checksum・signature・provenanceは別の保証をする のprovenance側の問題である。

Nixにはcontent-addressed objectを扱う仕組みが既にある一方、通常のderivation outputをfloating content-addressedにするca-derivationsはNix 2.35.2時点でもexperimental featureである。したがって「Nixはcontent-addressed package managerである」と一般化するのも正確ではない。

さらに、同じ入力を固定したから同じbytesが出るとは限らない。build時刻、filesystem order、乱数、toolchainの非決定性などがoutputに入り得るため、input-addressingとreproducible buildも別概念である。これは lockfileで依存を固定してもreproducible buildにはならない で扱う。

この区別はNix以外にも有用である。package managerを比較するときは、version、dependency graph、recipe hash、artifact digest、build provenanceをすべて「artifact identity」として一括りにせず、どの層の同一性を表しているのかを見る必要がある。

#ツールチェーン #security

出典

▸ ノート一覧に戻る