~/bend-docscommunity

proofs/crypto/chacha/proof.bend source

proofs/crypto/chacha/proof.bend on the hub · documented module

import Baseimport ../../../src/crypto/chacha/chacha20.bend as Iimport ../../../spec/crypto/chacha.bend as Rimport ./laws.bend as Lawsimport ./stream.bend as Timport ./xchacha.bend as Ximport ./involution.bend as V# Entry point: `bend proofs/crypto/chacha/proof.bend` checks every clause of# laws.bend (the core refinement is proofs/crypto/chacha/core.bend, the# byte-level stream stream.bend, HChaCha20/XChaCha20 xchacha.bend, the# involution involution.bend).def Laws.block_rounds(r, key, counter, nonce):  T.block_rounds_correct(r, key, counter, nonce)def Laws.encrypt_rounds(r, key, counter, nonce, plaintext):  T.encrypt_correct(r, key, counter, nonce, plaintext)def Laws.hchacha_rounds(r, key, nonce):  X.hchacha_rounds_correct(r, key, nonce)def Laws.hchacha20(key, nonce):  X.hchacha20_correct(key, nonce)def Laws.xencrypt(key, counter, nonce, plaintext):  X.xencrypt_correct(key, counter, nonce, plaintext)# ---- checked APIlaw when_true:  for +ok: Bool  for +x: List<&2, U32>  for +h: {ok == True{} : Bool}  {I.when(ok, x) == Some{x} : Maybe<&2, List<&2, U32>>}def when_true(ok, x, h):  %Equal.sym(Bool, ok, True{}, h) : {I.when(_, x) == Some{x} : Maybe<&2, List<&2, U32>>}  {==}law when_false:  for +ok: Bool  for +x: List<&2, U32>  for +h: {ok == False{} : Bool}  {I.when(ok, x) == None{} : Maybe<&2, List<&2, U32>>}def when_false(ok, x, h):  %Equal.sym(Bool, ok, False{}, h) : {I.when(_, x) == None{} : Maybe<&2, List<&2, U32>>}  {==}law valid_true:  for +key: List<&2, U32>  for +nonce: List<&2, U32>  for +n: Nat  for +hk: {List.length(&2, U32, key) == 32n : Nat}  for +hn: {List.length(&2, U32, nonce) == n : Nat}  {I.valid(key, nonce, n) == True{} : Bool}def is_eq_self(+n: Nat) -> {Nat.is_eq(n, n) == True{} : Bool}:  match n:    case 0n: {==}    case 1n+p: is_eq_self(p)def valid_true(key, nonce, n, hk, hn):  %Equal.sym(Nat, List.length(&2, U32, key), 32n, hk) :    {Bool.and(Nat.is_eq(_, 32n), Nat.is_eq(List.length(&2, U32, nonce), n)) == True{} : Bool}  %Equal.sym(Nat, List.length(&2, U32, nonce), n, hn) :    {Bool.and(Nat.is_eq(32n, 32n), Nat.is_eq(_, n)) == True{} : Bool}  is_eq_self(n)def Laws.chacha20_block.valid(key, counter, nonce, hk, hn):  Equal.trans(Maybe<&2, List<&2, U32>>, I.chacha20_block(key, counter, nonce), Some{I.block_rounds(10n, key, counter, nonce)}, Some{R.block(key, counter, nonce)},    when_true(I.valid(key, nonce, 12n), I.block_rounds(10n, key, counter, nonce), valid_true(key, nonce, 12n, hk, hn)),    Equal.cong(List<&2, U32>, Maybe<&2, List<&2, U32>>, l => Some{l}, I.block_rounds(10n, key, counter, nonce), R.block(key, counter, nonce), T.block_rounds_correct(10n, key, counter, nonce)))def Laws.chacha20_block.invalid(key, counter, nonce, h):  when_false(I.valid(key, nonce, 12n), I.block_rounds(10n, key, counter, nonce), h)def Laws.chacha20.valid(key, counter, nonce, plaintext, hk, hn):  Equal.trans(Maybe<&2, List<&2, U32>>, I.chacha20(key, counter, nonce, plaintext), Some{I.encrypt_rounds(10n, key, counter, nonce, plaintext)}, Some{R.encrypt(key, counter, nonce, plaintext)},    when_true(I.valid(key, nonce, 12n), I.encrypt_rounds(10n, key, counter, nonce, plaintext), valid_true(key, nonce, 12n, hk, hn)),    Equal.cong(List<&2, U32>, Maybe<&2, List<&2, U32>>, l => Some{l}, I.encrypt_rounds(10n, key, counter, nonce, plaintext), R.encrypt(key, counter, nonce, plaintext), T.encrypt_correct(10n, key, counter, nonce, plaintext)))def Laws.chacha20.invalid(key, counter, nonce, plaintext, h):  when_false(I.valid(key, nonce, 12n), I.encrypt_rounds(10n, key, counter, nonce, plaintext), h)def Laws.hchacha20.valid(key, nonce, hk, hn):  Equal.trans(Maybe<&2, List<&2, U32>>, I.hchacha20(key, nonce), Some{I.hchacha20_unchecked(key, nonce)}, Some{R.hchacha20(key, nonce)},    when_true(I.valid(key, nonce, 16n), I.hchacha20_unchecked(key, nonce), valid_true(key, nonce, 16n, hk, hn)),    Equal.cong(List<&2, U32>, Maybe<&2, List<&2, U32>>, l => Some{l}, I.hchacha20_unchecked(key, nonce), R.hchacha20(key, nonce), X.hchacha20_correct(key, nonce)))def Laws.hchacha20.invalid(key, nonce, h):  when_false(I.valid(key, nonce, 16n), I.hchacha20_unchecked(key, nonce), h)def Laws.xchacha20.valid(key, counter, nonce, plaintext, hk, hn):  Equal.trans(Maybe<&2, List<&2, U32>>, I.xchacha20(key, counter, nonce, plaintext), Some{I.xencrypt_unchecked(key, counter, nonce, plaintext)}, Some{R.xencrypt(key, counter, nonce, plaintext)},    when_true(I.valid(key, nonce, 24n), I.xencrypt_unchecked(key, counter, nonce, plaintext), valid_true(key, nonce, 24n, hk, hn)),    Equal.cong(List<&2, U32>, Maybe<&2, List<&2, U32>>, l => Some{l}, I.xencrypt_unchecked(key, counter, nonce, plaintext), R.xencrypt(key, counter, nonce, plaintext), X.xencrypt_correct(key, counter, nonce, plaintext)))def Laws.xchacha20.invalid(key, counter, nonce, plaintext, h):  when_false(I.valid(key, nonce, 24n), I.xencrypt_unchecked(key, counter, nonce, plaintext), h)# ---- propertiesdef Laws.involution(r, key, counter, nonce, plaintext):  +ct = I.encrypt_rounds(r, key, counter, nonce, plaintext)  +sct = R.encrypt_rounds(r, key, counter, nonce, plaintext)  Equal.trans(List<&2, U32>, I.encrypt_rounds(r, key, counter, nonce, ct), R.encrypt_rounds(r, key, counter, nonce, ct), plaintext,    T.encrypt_correct(r, key, counter, nonce, ct),    Equal.trans(List<&2, U32>, R.encrypt_rounds(r, key, counter, nonce, ct), R.encrypt_rounds(r, key, counter, nonce, sct), plaintext,      Equal.cong(List<&2, U32>, List<&2, U32>, l => R.encrypt_rounds(r, key, counter, nonce, l), ct, sct, T.encrypt_correct(r, key, counter, nonce, plaintext)),      V.involution(r, key, counter, nonce, plaintext)))def Laws.xinvolution(key, counter, nonce, plaintext):  +ct = I.xencrypt_unchecked(key, counter, nonce, plaintext)  +sct = R.xencrypt(key, counter, nonce, plaintext)  Equal.trans(List<&2, U32>, I.xencrypt_unchecked(key, counter, nonce, ct), R.xencrypt(key, counter, nonce, ct), plaintext,    X.xencrypt_correct(key, counter, nonce, ct),    Equal.trans(List<&2, U32>, R.xencrypt(key, counter, nonce, ct), R.xencrypt(key, counter, nonce, sct), plaintext,      Equal.cong(List<&2, U32>, List<&2, U32>, l => R.xencrypt(key, counter, nonce, l), ct, sct, X.xencrypt_correct(key, counter, nonce, plaintext)),      V.involution(10n, R.xsubkey(key, nonce), counter, R.xnonce(nonce), plaintext)))def Laws.encrypt_length(r, key, counter, nonce, plaintext):  %Equal.sym(List<&2, U32>, I.encrypt_rounds(r, key, counter, nonce, plaintext), R.encrypt_rounds(r, key, counter, nonce, plaintext), T.encrypt_correct(r, key, counter, nonce, plaintext)) :    {List.length(&2, U32, _) == List.length(&2, U32, plaintext) : Nat}  V.encrypt_length(r, key, counter, nonce, plaintext)def Laws.block_length(r, key, counter, nonce):  T.block_length(r, key, counter, nonce)def Laws.hchacha_length(r, key, nonce):  match key:    case Nil{}: {==}    case b <> rest: {==}