cashcat0.jpg
cashcat1.jpg
cashcat2.jpg
cashcats.p00
cashcats.p01
Cashcat pictures from @CatsAndMoney.
cashcat0.jpg: aa b3 3f 2f 13 33 ...
cashcat1.jpg: bb 34 25 36 3f ed ...
cashcat2.jpg: cc 35 d3 3f ff c0 ...
|
|
ComputeParity
|
\|/
cashcats.p00: 14 34 ...
cashcats.p01: 25 53 ...
…and so on.
cashcat0.jpg: XX XX XX XX XX XX ... (sha1 mismatch) cashcat1.jpg: bb 34 25 36 3f ed ... cashcat2.jpg: ?? ?? ?? ?? ?? ?? ... (missing) cashcats.p00: 14 34 11 50 3f fe ... cashcats.p01: 25 53 23 36 1f 3d ... | | ReconstructData | \|/ cashcat0.jpg: aa b3 ... cashcat1.jpg: bb 34 ... cashcat2.jpg: cc 35 ...…and so on.
or
$$ \begin{aligned} p_0 &= 1/3 \cdot d_0 + 1/2 \cdot d_1 + 1/1 \cdot d_2 \\ p_1 &= 1/4 \cdot d_0 + 1/3 \cdot d_1 + 1/2 \cdot d_2 \end{aligned}$$
⚠️ For now, rational numbers (fractions), not bytes. ⚠️
Generate parity matrix with parityCount=2 rows and
dataCount=3 columns.
for i, j in range(0, 2) × range(0, 3)
Called a Cauchy matrix.
Reconstruction: Start with the parity computation…
$\begin{pmatrix} p_0 \\ p_1 \end{pmatrix} = \begin{pmatrix} 1/3 & 1/2 & 1/1 \\ 1/4 & 1/3 & 1/2 \end{pmatrix} \cdot \begin{pmatrix} d_0 \\ d_1 \\ d_2 \end{pmatrix}$Append to identity function…
$\begin{pmatrix} d_0 \\ d_1 \\ d_2 \\ p_0 \\ p_1 \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ 1/3 & 1/2 & 1/1 \\ 1/4 & 1/3 & 1/2 \end{pmatrix} \cdot \begin{pmatrix} d_0 \\ d_1 \\ d_2 \end{pmatrix}$Remove unknown rows…
$\begin{pmatrix} \xcancel{d_0} \\ d_1 \\ \xcancel{d_2} \\ p_0 \\ p_1 \end{pmatrix} = \begin{pmatrix} \xcancel{1} & \xcancel{0} & \xcancel{0} \\ 0 & 1 & 0 \\ \xcancel{0} & \xcancel{0} & \xcancel{1} \\ 1/3 & 1/2 & 1/1 \\ 1/4 & 1/3 & 1/2 \end{pmatrix} \cdot \begin{pmatrix} d_0 \\ d_1 \\ d_2 \end{pmatrix}$Remove unknown rows…
$\begin{pmatrix} d_1 \\ p_0 \\ p_1 \end{pmatrix} = \begin{pmatrix} 0 & 1 & 0 \\ 1/3 & 1/2 & 1/1 \\ 1/4 & 1/3 & 1/2 \end{pmatrix} \cdot \begin{pmatrix} d_0 \\ d_1 \\ d_2 \end{pmatrix} $Remaining problem…
How to compute parity bytes instead of parity numbers?
interface Field<T> {
static Zero: T, One: T
plus(b: T): T // $a \oplus b$
negate(): T // $-a$
times(b: T): T // $a \otimes b$
reciprocate(): T // $a^{-1}$, for $a \ne 0$
equals(b: T): bool // $a = b$
}
// $a \ominus b$
minus(b: T): T => this.plus(b.negate())
// $a \oslash b$
dividedBy(b: T): T => this.times(b.reciprocate())
reciprocate() => {
if (this === 0) { throw new Error("Division by zero"); }
for (let i = 0; i < 257; i += 1) {
if ((this * i) % 257 === 1) { return i; }
}
throw new Error("Shouldn't get here!");
} a = 23 = 10111b
^ b = 54 = 110110b
-------
100001b
so $a \oplus b = 100001_{\mathrm{b}} = 33$.
a ^ a = 0. a = 23 = 10111b
^* b = 54 = 110110b
------------
10111
^ 10111
^ 10111
^ 10111
------------
1111100010b
so $a \otimes b = 1111100010_{\mathrm{b}} = 994$.
11b
--------
b = 19 = 10011b )110111b = 55 = a
^ 10011
-----
10001
^ 10011
-----
10b
so $a \oslash b = 11_{\mathrm{b}} = 3$
with remainder $10_{\mathrm{b}} = 3$.
class Field256Element implements Field<Field256Element> {
static Zero = 0, One = 1
plus(b) => (a ^ b)
negate() => a
times(b): => clmod(clmul(a, b), 283)
reciprocate() => // next slide
equals(b) => (a === b)
}
reciprocate() => {
if (this === 0) { throw new Error("Division by zero"); }
for (let i = 0; i < 256; i += 1) {
if (clmod(clmul(this, i), 283) === 1) { return i; }
}
throw new Error("Shouldn't get here!");
}
Field256Element, i.e. bytes with carry-less arithmetic mod 283.