ob.js (3925B)
1 // ++ ob 2 // 3 // See arvo/sys/hoon.hoon. 4 5 const BN = require('bn.js') 6 const { muk } = require('./muk') 7 8 const ux_1_0000 = new BN('10000', 'hex') 9 const ux_ffff_ffff = new BN('ffffffff', 'hex') 10 const ux_1_0000_0000 = new BN('100000000', 'hex') 11 const ux_ffff_ffff_ffff_ffff = new BN('ffffffffffffffff', 'hex') 12 const ux_ffff_ffff_0000_0000 = new BN('ffffffff00000000', 'hex') 13 14 const u_65535 = new BN('65535') 15 const u_65536 = new BN('65536') 16 17 // a PRF for j in { 0, .., 3 } 18 const F = (j, arg) => { 19 const raku = [ 20 0xb76d5eed, 21 0xee281300, 22 0x85bcae01, 23 0x4b387af7, 24 ] 25 26 return muk(raku[j], 2, arg) 27 } 28 29 /** 30 * Conceal structure v3. 31 * 32 * @param {String, Number, BN} pyn 33 * @return {BN} 34 */ 35 const fein = (arg) => { 36 const loop = (pyn) => { 37 const lo = pyn.and(ux_ffff_ffff) 38 const hi = pyn.and(ux_ffff_ffff_0000_0000) 39 40 return pyn.gte(ux_1_0000) && pyn.lte(ux_ffff_ffff) 41 ? ux_1_0000.add(feis(pyn.sub(ux_1_0000))) 42 : pyn.gte(ux_1_0000_0000) && pyn.lte(ux_ffff_ffff_ffff_ffff) 43 ? hi.or(loop(lo)) 44 : pyn 45 } 46 47 return loop(new BN(arg)) 48 } 49 50 /** 51 * Restore structure v3. 52 * 53 * @param {String, Number, BN} cry 54 * @return {BN} 55 */ 56 const fynd = (arg) => { 57 const loop = (cry) => { 58 const lo = cry.and(ux_ffff_ffff) 59 const hi = cry.and(ux_ffff_ffff_0000_0000) 60 61 return cry.gte(ux_1_0000) && cry.lte(ux_ffff_ffff) 62 ? ux_1_0000.add(tail(cry.sub(ux_1_0000))) 63 : cry.gte(ux_1_0000_0000) && cry.lte(ux_ffff_ffff_ffff_ffff) 64 ? hi.or(loop(lo)) 65 : cry 66 } 67 68 return loop(new BN(arg)) 69 } 70 71 /** 72 * Generalised Feistel cipher. 73 * 74 * See: Black and Rogaway (2002), "Ciphers with arbitrary finite domains." 75 * 76 * Note that this has been adjusted from the reference paper in order to 77 * support some legacy behaviour. 78 * 79 * @param {String, Number, BN} 80 * @return {BN} 81 */ 82 const feis = arg => 83 Fe(4, u_65535, u_65536, ux_ffff_ffff, F, new BN(arg)) 84 85 const Fe = (r, a, b, k, f, m) => { 86 const c = fe(r, a, b, f, m) 87 return ( 88 c.lt(k) 89 ? c 90 : fe(r, a, b, f, c) 91 ) 92 } 93 94 const fe = (r, a, b, f, m) => { 95 const loop = (j, ell, arr) => { 96 if (j > r) { 97 return ( 98 r % 2 !== 0 99 ? a.mul(arr).add(ell) 100 : arr.eq(a) 101 ? a.mul(arr).add(ell) 102 : a.mul(ell).add(arr) 103 ) 104 } else { 105 const eff = f(j - 1, arr) 106 107 const tmp = 108 j % 2 !== 0 109 ? ell.add(eff).mod(a) 110 : ell.add(eff).mod(b) 111 112 return loop(j + 1, arr, tmp) 113 } 114 } 115 116 const L = m.mod(a) 117 const R = m.div(a) 118 119 return loop(1, L, R) 120 } 121 122 /** 123 * Reverse 'feis'. 124 * 125 * See: Black and Rogaway (2002), "Ciphers with arbitrary finite domains." 126 * 127 * Note that this has been adjusted from the reference paper in order to 128 * support some legacy behaviour. 129 * 130 * @param {Number, String, BN} arg 131 * @return {BN} 132 */ 133 const tail = arg => 134 Fen(4, u_65535, u_65536, ux_ffff_ffff, F, new BN(arg)) 135 136 const Fen = (r, a, b, k, f, m) => { 137 const c = fen(r, a, b, f, m) 138 return ( 139 c.lt(k) 140 ? c 141 : fen(r, a, b, f, c) 142 ) 143 } 144 145 const fen = (r, a, b, f, m) => { 146 const loop = (j, ell, arr) => { 147 if (j < 1) { 148 return a.mul(arr).add(ell) 149 } else { 150 const eff = f(j - 1, ell) 151 152 // NB (jtobin): 153 // 154 // Slight deviation from B&R (2002) here to prevent negative values. We 155 // add 'a' or 'b' to arr as appropriate and reduce 'eff' modulo the same 156 // number before performing subtraction. 157 // 158 const tmp = 159 j % 2 !== 0 160 ? arr.add(a).sub(eff.mod(a)).mod(a) 161 : arr.add(b).sub(eff.mod(b)).mod(b) 162 163 return loop(j - 1, tmp, ell) 164 } 165 } 166 167 const ahh = 168 r % 2 !== 0 169 ? m.div(a) 170 : m.mod(a) 171 172 const ale = 173 r % 2 !== 0 174 ? m.mod(a) 175 : m.div(a) 176 177 const L = 178 ale.eq(a) 179 ? ahh 180 : ale 181 182 const R = 183 ale.eq(a) 184 ? ale 185 : ahh 186 187 return loop(r, L, R) 188 } 189 190 module.exports = { 191 F, 192 193 fe, 194 Fe, 195 feis, 196 fein, 197 198 fen, 199 Fen, 200 tail, 201 fynd 202 }