|
参考了micro-ecc部分代码。内联汇编尚未写完。 $ W2 @; f+ ]: K% {, y 代码在STM32L496上验证通过,计算时间是23毫秒。0 V* b: b3 V; Z& c* j% K5 X 只支持secp256k1曲线. (友情提供上sha256 MD算法);/ k; U4 c& k4 p- N- f) } & i0 ]/ S7 i0 m( C' a #include <stdint.h> #include <stdio.h> #include <string.h>% z- ^' r d8 f) U7 V #define EC_BYTES 32 ?1 t R' D8 d& v8 m #if __STDC_VERSION__ >= 199901L$ X% Z0 a2 d4 b$ ~* S #define RESTRICT restrict #else #define RESTRICT #endif typedef uint32_t ec_word_t;9 u5 s( G* H E L0 [ typedef uint64_t ec_dword_t; typedef unsigned wordcount_t;$ A0 j; v' g" P4 F* O* N/ z #define HIGH_BIT_SET 0x80000000/ h2 b" t- E& C #define ec_WORD_BITS 32- B( o$ h3 L2 n1 f0 T #define ec_WORD_BITS_SHIFT 5' Y7 P5 L8 ] _ #define ec_WORD_BITS_MASK 0x01F #define ec_WORDS 8* N( f" E$ U* C: d1 L& _ #define ec_N_WORDS 8, I# e* z. ]7 J1 |9 R - J8 u! e' Z- N$ S- y3 u #define vli_modSub_fast(result, left, right) vli_modSub((result), (left), (right), curve_p) #define vli_modSquare_fast(result, left) vli_modMult_fast((result), (left), (left))8 \+ _8 v% l7 d #define EVEN(vli) (!(vli[0] & 1)) * h7 }7 Y7 C/ s, J typedef struct EccPoint {( ~9 d. |4 O7 U/ G& ^ ec_word_t x[ec_WORDS];0 n8 `# w( \. A. X8 C ]" | ec_word_t y[ec_WORDS];+ @& N, T0 _: B+ I* Y } EccPoint; static const ec_word_t curve_p[ec_WORDS] = {0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};) I, j5 t& f8 t$ I( C //static const ec_word_t curve_b[ec_WORDS] = {0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};: I' o( C5 {" U- k0 i5 K static const EccPoint curve_G = {{0x16F81798, 0x59F2815B, 0x2DCE28D9, 0x029BFCDB, 0xCE870B07, 0x55A06295, 0xF9DCBBAC, 0x79BE667E}, \ {0xFB10D4B8, 0x9C47D08F, 0xA6855419, 0xFD17B448, 0x0E1108A8, 0x5DA4FBFC, 0x26A3C465, 0x483ADA77}};4 n+ W$ I9 r/ W* l% b static const ec_word_t curve_n[ec_N_WORDS] = {0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; + `9 o6 x) M7 @# H7 j: ^- m! } static void vli_rshift1(ec_word_t *vli); static void vli2_rshift1(ec_word_t *vli);4 X M( G/ r! L) [* V7 \ static void vli_set(ec_word_t *dest, const ec_word_t *src);7 A; D' T: e9 n static void vli_clear(ec_word_t *vli);* H! v: I6 R: t* v static void vli_bytesToNative(uint32_t *native, const uint8_t *bytes);0 {% g: Q0 q7 r! s6 q1 V; d6 f static void vli_modMult_n(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);/ Z% e5 o- D; V3 d static void vli_mult(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);) }. W0 q& |$ L$ S8 Q' U static void vli_modSub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod);+ w5 }, W, j9 ` static void vli_modMult_fast(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);5 W% N0 Q; y4 @( z static void vli_modInv(ec_word_t *result, const ec_word_t *input, const ec_word_t *mod); static void vli_modAdd(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod);7 H; p3 m& [* D$ W' s5 u! m static void vli_mmod_fast(ec_word_t *RESTRICT result, ec_word_t *RESTRICT product); static int vli_equal(const ec_word_t *left, const ec_word_t *right); static ec_word_t vli_testBit(const ec_word_t *vli, int bit); static int vli_cmp(const ec_word_t *left, const ec_word_t *right);9 `% y4 ^. a5 y4 u. p& D static ec_word_t vli_isZero(const ec_word_t *vli); static ec_word_t vli_sub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right);( z% z1 W4 R$ y static wordcount_t vli_numDigits(const ec_word_t *vli, wordcount_t max_words); L) \. T8 c) X- _ static int vli_numBits(const ec_word_t *vli, wordcount_t max_words);4 @! l6 b" B8 A5 Z/ r static int smax(int a, int b);1 J! f9 I6 q6 n2 L5 m7 r$ ~ static void apply_z(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1, const ec_word_t * RESTRICT Z);6 G* h, r% A! ~% V( f9 y static void omega_mult(uint32_t * RESTRICT result, const uint32_t * RESTRICT right);: ]3 [" W# S9 p static void muladd(ec_word_t a, ec_word_t b, ec_word_t *r0, ec_word_t *r1, ec_word_t *r2);& G1 U$ V) R2 t$ z4 Q! v$ t static void XYcZ_add(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1, ec_word_t * RESTRICT X2, ec_word_t * RESTRICT Y2); static void EccPoint_double_jacobian(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1, ec_word_t * RESTRICT Z1); : J- u; j1 [3 R int ec_verify(const uint8_t public_key[64], const uint8_t hash[32], const uint8_t signature[64]) { ec_word_t u1[ec_N_WORDS], u2[ec_N_WORDS]; ec_word_t z[ec_N_WORDS];/ P- ]5 R* \8 f EccPoint public, sum;0 x2 @( S7 y& f1 D ec_word_t rx[ec_WORDS]; ec_word_t ry[ec_WORDS]; ec_word_t tx[ec_WORDS]; ec_word_t ty[ec_WORDS]; ec_word_t tz[ec_WORDS]; const EccPoint *points[4];* h: M( T. M' M3 n* J2 t% A const EccPoint *point; int numBits; int i; ec_word_t r[ec_N_WORDS], s[ec_N_WORDS]; r[ec_N_WORDS - 1] = 0; s[ec_N_WORDS - 1] = 0;6 t: Y! I- _* G8 i9 J/ K# m+ {5 v ) J: O S6 u5 L- b* C$ j$ n vli_bytesToNative(public.x, public_key); vli_bytesToNative(public.y, public_key + EC_BYTES);3 O. C$ ^, f% J/ X& D vli_bytesToNative(r, signature); vli_bytesToNative(s, signature + EC_BYTES); if (vli_isZero(r) || vli_isZero(s)) { /* r, s must not be 0. */9 ~$ y0 P m% _* `1 l) k return 0; } vli_modInv(z, s, curve_n); u1[ec_N_WORDS - 1] = 0;$ H6 `8 M: m& L6 n- O/ f3 m vli_bytesToNative(u1, hash); vli_modMult_n(u1, u1, z); /* u1 = e/s */4 s" J! M6 O' H4 `7 z* |+ D vli_modMult_n(u2, r, z); /* u2 = r/s */ /* Calculate sum = G + Q. */ vli_set(sum.x, public.x);0 h; O! g4 x! w, X" T1 C. f vli_set(sum.y, public.y);/ _: C$ g {: P8 S+ P, ~8 d vli_set(tx, curve_G.x); vli_set(ty, curve_G.y);' r* ~% z8 b4 } vli_modSub_fast(z, sum.x, tx); /* Z = x2 - x1 */6 `; j1 \8 A/ v5 d! ^ XYcZ_add(tx, ty, sum.x, sum.y); vli_modInv(z, z, curve_p); /* Z = 1/Z */ apply_z(sum.x, sum.y, z); ; r3 c& o- G; i. x8 V' X' { /* Use Shamir's trick to calculate u1*G + u2*Q */, O4 c1 ?; E8 q! w# |' g; a1 J points[0] = 0;1 u: w& v+ r2 t3 s points[1] = &curve_G;. W8 L. k* c! t3 U1 z points[2] = &public; points[3] = ∑ numBits = smax(vli_numBits(u1, ec_N_WORDS), vli_numBits(u2, ec_N_WORDS)); point = points[(!!vli_testBit(u1, numBits - 1)) | ((!!vli_testBit(u2, numBits - 1)) << 1)]; vli_set(rx, point->x);. h: Y2 ?3 E* u" i- ~ vli_set(ry, point->y);4 a2 i& {; u& P; x7 J: b1 M vli_clear(z);% L, E" ]- p$ K0 y+ W t z[0] = 1; " H" I! r4 D" h& A2 C; z for (i = numBits - 2; i >= 0; --i) {. N% d6 w9 |0 o. N/ \ ec_word_t index; EccPoint_double_jacobian(rx, ry, z); $ k: j7 P5 y+ [ index = (!!vli_testBit(u1, i)) | ((!!vli_testBit(u2, i)) << 1); point = points[index]; if (point) {& s. W; d2 K5 T5 ^) J, G F! Z vli_set(tx, point->x); vli_set(ty, point->y);, |/ z7 _5 s0 G1 M% w* E/ }& E, P apply_z(tx, ty, z);( |( f6 I- |9 ?; q$ `) n+ S vli_modSub_fast(tz, rx, tx); /* Z = x2 - x1 */& y+ U! S! g0 X6 m/ M XYcZ_add(tx, ty, rx, ry); vli_modMult_fast(z, z, tz); }# M6 A6 v, e1 O. m8 v; @ }. Y5 `8 ^7 K3 z& b2 h7 f vli_modInv(z, z, curve_p); /* Z = 1/Z */7 o3 p2 K, y# R- t7 Z$ l* \7 _* O apply_z(rx, ry, z);8 [0 l$ t" Z v" S0 ` return vli_equal(rx, r);; j- O/ K$ M p1 o3 W. w } static int vli_equal(const ec_word_t *left, const ec_word_t *right) { ec_word_t result = 0;! f9 }3 {" @) }- Z% V: y int i; for (i = ec_WORDS - 1; i >= 0; --i) {* m; E7 x2 x( c L+ j result |= (left[i] ^ right[i]);) ?7 H* X. n8 X4 Q v }7 @; n9 u0 w& S% N7 X, k return (result == 0);7 H# g% {/ [% @& \ } static ec_word_t vli_add(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) { ec_word_t carry = 0; wordcount_t i; for (i = 0; i < ec_WORDS; ++i) { ec_word_t sum = left[i] + right[i] + carry; if (sum != left[i]) { carry = (sum < left[i]);2 k5 n* `2 r2 p+ R5 x } result[i] = sum; }+ b2 I0 ?4 U/ p& r6 o& Q( i J! o return carry; }+ ~4 R5 L, r; X- D# B+ i 4 [, Q! R7 _5 f ^/ G$ W static void vli_bytesToNative(uint32_t *native, const uint8_t *bytes) {/ l! Y' u1 B' w unsigned i; for (i = 0; i < ec_WORDS; ++i) { const uint8_t *digit = bytes + 4 * (ec_WORDS - 1 - i);# `: S! s4 C1 ?6 X" j( m+ V native[i] = ((uint32_t)digit[0] << 24) | ((uint32_t)digit[1] << 16) |1 B/ z: L8 c( z7 n ((uint32_t)digit[2] << 8) | (uint32_t)digit[3];0 {# i8 a) E$ v% s# O5 E }3 y3 |+ G; x: c+ C, K H ? }! t& \) d- L7 S) X- O! d3 @6 ] static ec_word_t vli_isZero(const ec_word_t *vli) {# C6 T, B' |8 j7 U }$ U1 L wordcount_t i;/ G6 w p' k; s6 _: v6 w for (i = 0; i < ec_WORDS; ++i) {+ v* K/ [0 q# W e+ G( m9 t8 U, O8 q if (vli[i]) {- q* E( H- x: i! {. q( p return 0; } }+ F: v# ]% Y$ E- v4 D return 1; }/ R0 B/ A6 P3 h# |$ f0 z static ec_word_t vli_sub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) {3 L' _5 D1 j) p! {7 g0 r) \+ W+ x ec_word_t borrow = 0; wordcount_t i;( K. x+ U, }2 F) v+ A+ h for (i = 0; i < ec_WORDS; ++i) {" w9 l! H5 }( z, [ ec_word_t diff = left[i] - right[i] - borrow;2 v4 z. l4 g8 S" {- | if (diff != left[i]) {5 l5 C; ^+ c1 L1 C borrow = (diff > left[i]); }( z; }2 F6 l) L) i result[i] = diff;. ?( L3 u$ ^2 ~8 W5 r* W }+ t w3 W) k& J4 w0 g3 w return borrow; }. [* I( m) {* w' C static ec_word_t vli2_sub(ec_word_t *result,' G& S' X- Q9 K const ec_word_t *left, const ec_word_t *right) { ec_word_t borrow = 0; wordcount_t i;5 [& L& P$ u) F d. p for (i = 0; i < ec_WORDS * 2; ++i) {7 V Z$ u& _0 r ec_word_t diff = left[i] - right[i] - borrow; if (diff != left[i]) { borrow = (diff > left[i]); }2 M8 F3 d" K* o3 x) ^; a3 f result[i] = diff; } return borrow;6 B, o- H4 E/ a' [, Y, h6 I } /* Computes result = (left * right) % curve_n. */ static void vli_modMult_n(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) { ec_word_t product[2 * ec_WORDS];, w3 t5 b- }3 [ ec_word_t modMultiple[2 * ec_WORDS];' a+ i) K) T: g' C ec_word_t tmp[2 * ec_WORDS];8 C. s4 A- b! ]* G+ w i ec_word_t *v[2] = {tmp, product};: u. k u* a- V+ J: P int i; ec_word_t index = 1;; J/ |9 D( |# r5 { vli_mult(product, left, right);6 ]! g7 o3 v- l) W4 [ vli_set(modMultiple + ec_WORDS, curve_n); /* works if curve_n has its highest bit set */% m" V5 i; C4 y6 i4 T0 |; K/ } vli_clear(modMultiple);- Q# V# `5 p* L( p9 V 1 v- V% j/ d, ? Y q4 { for (i = 0; i <= EC_BYTES * 8; ++i) {! j- \. C# b9 R2 y( v5 X7 b ec_word_t borrow = vli2_sub(v[1 - index], v[index], modMultiple);6 T5 B9 I4 K p4 W( L- Z8 w# `: `- s index = !(index ^ borrow); /* Swap the index if there was no borrow */ |+ x2 O- N1 B8 {9 N- _" v vli2_rshift1(modMultiple); } vli_set(result, v[index]); } static void vli_mult(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) {/ ~* R f0 Y p" H ec_word_t r0 = 0; ec_word_t r1 = 0;7 `# D5 x3 Q4 m. Y7 m& E( r ec_word_t r2 = 0; wordcount_t i, k;: N. {4 i6 @( x' F3 P5 X /* Compute each digit of result in sequence, maintaining the carries. */) ]. L* o+ C$ z0 i% M for (k = 0; k < ec_WORDS; ++k) {# k1 D& V7 c1 c) z- n for (i = 0; i <= k; ++i) {' @( W- _+ c4 B4 H$ Q9 A muladd(left[i], right[k - i], &r0, &r1, &r2);4 s4 m4 q% }8 x# X# G. U) `: d5 q }" w) Q8 N5 m$ G; h result[k] = r0;+ S; X# t, D! s! R$ @ r0 = r1;, `) l% o/ F: \. N, f! ` r1 = r2;9 ~* S1 X' y3 H6 M3 h" X r2 = 0;$ g4 J T. U$ x, I y }& \' m5 Y8 _8 m. D7 F1 y for (k = ec_WORDS; k < ec_WORDS * 2 - 1; ++k) {% o2 G: j0 o. Z- ~5 X0 E for (i = (k + 1) - ec_WORDS; i < ec_WORDS; ++i) { muladd(left[i], right[k - i], &r0, &r1, &r2); }8 W+ e3 I4 ^7 u9 \+ O6 W result[k] = r0;& h$ k2 S% M; k2 c! ] r0 = r1;" \. S5 L0 J5 T r1 = r2;) Y& q+ T; v6 \5 W( r r2 = 0; } result[ec_WORDS * 2 - 1] = r0; } ; i0 K9 H" E. ~0 _" B) s static void muladd(ec_word_t a, ec_word_t b, ec_word_t *r0, ec_word_t *r1, ec_word_t *r2) { ec_dword_t p = (ec_dword_t)a * b; ec_dword_t r01 = ((ec_dword_t)(*r1) << ec_WORD_BITS) | *r0; r01 += p; *r2 += (r01 < p);% S( O6 U; |& S- X8 \ *r1 = r01 >> ec_WORD_BITS; *r0 = (ec_word_t)r01; } //#define muladd_exists 1 static void vli_rshift1(ec_word_t *vli) { ec_word_t *end = vli;& U" }8 ^3 t$ j+ k* W; E( C ec_word_t carry = 0; t: z/ a- l E5 I+ T3 S2 P v$ F vli += ec_WORDS;/ O# `- H+ m& ^ while (vli-- > end) {) v& `; ^# y% @( h( G ec_word_t temp = *vli; *vli = (temp >> 1) | carry; carry = temp << (ec_WORD_BITS - 1);6 o* B/ u4 U3 B' n1 n } }0 e$ c5 j' k4 x" E9 ]: ]5 a static void vli2_rshift1(ec_word_t *vli) { vli_rshift1(vli);# f" H, t( g8 l9 a% m( l vli[ec_WORDS - 1] |= vli[ec_WORDS] << (ec_WORD_BITS - 1);2 }1 ~! u+ k0 B/ z vli_rshift1(vli + ec_WORDS);" W5 q/ E3 ?* S+ ^) Y } static void vli_modSub(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod) { ec_word_t l_borrow = vli_sub(result, left, right);+ y9 ?4 Y a7 u$ m1 E/ D if (l_borrow) {. D8 Z2 _- k) Y: h /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, we can get the correct result from result + mod (with overflow). */ vli_add(result, result, mod);; S! I8 ]/ R" q9 c& H } } static void vli_set(ec_word_t *dest, const ec_word_t *src) {+ k( T! ?+ \, y/ e0 N% l/ m) R wordcount_t i;+ U: [: A" i% F for (i = 0; i < ec_WORDS; ++i) {2 s! r$ \7 J- p/ e: w dest[i] = src[i];4 Z8 s5 P+ s7 L" S8 i9 ^ } }! p- s( A2 o( c; i2 D! y - m$ `& L! K2 q1 X! z! [ static void XYcZ_add(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1,2 @. T# k' t' [5 d5 f. M5 g, L ec_word_t * RESTRICT X2, ec_word_t * RESTRICT Y2) {5 F' V& L: ?3 U! p' ` /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */- L' e$ Y$ {- M ec_word_t t5[ec_WORDS]; vli_modSub_fast(t5, X2, X1); /* t5 = x2 - x1 */' J! J/ J8 K! I# G/ K5 J6 R vli_modSquare_fast(t5, t5); /* t5 = (x2 - x1)^2 = A */ vli_modMult_fast(X1, X1, t5); /* t1 = x1*A = B */ vli_modMult_fast(X2, X2, t5); /* t3 = x2*A = C */ vli_modSub_fast(Y2, Y2, Y1); /* t4 = y2 - y1 */ vli_modSquare_fast(t5, Y2); /* t5 = (y2 - y1)^2 = D */ @+ I* [8 O* K/ m% q8 V* V$ y , n# O ~2 Q. Q) Q" a$ Y vli_modSub_fast(t5, t5, X1); /* t5 = D - B */ vli_modSub_fast(t5, t5, X2); /* t5 = D - B - C = x3 */ vli_modSub_fast(X2, X2, X1); /* t3 = C - B */( N0 N/ z3 T2 v1 L2 V) h; {7 X vli_modMult_fast(Y1, Y1, X2); /* t2 = y1*(C - B) */ vli_modSub_fast(X2, X1, t5); /* t3 = B - x3 */* [7 B" y G7 F7 h vli_modMult_fast(Y2, Y2, X2); /* t4 = (y2 - y1)*(B - x3) */ vli_modSub_fast(Y2, Y2, Y1); /* t4 = y3 */- t1 {% G' Q, w. M $ G& f* r J9 Y0 W* ` vli_set(X2, t5);) z& d$ r3 ^* Q* M+ r } $ V+ _) u5 s1 t2 v! a, u4 H/ m7 @ static void EccPoint_double_jacobian(ec_word_t * RESTRICT X1,4 d" _" p7 w" T; m8 P ec_word_t * RESTRICT Y1, ec_word_t * RESTRICT Z1) { /* t1 = X, t2 = Y, t3 = Z */ ec_word_t t4[ec_WORDS]; ec_word_t t5[ec_WORDS]; if (vli_isZero(Z1)) {5 _* p' \$ E& `2 N+ s% L return; }2 u" f" N5 p* e3 P; m( J' v vli_modSquare_fast(t5, Y1); /* t5 = y1^2 */( C L- l3 r" S- k vli_modMult_fast(t4, X1, t5); /* t4 = x1*y1^2 = A */ vli_modSquare_fast(X1, X1); /* t1 = x1^2 */9 T4 X6 O2 i b4 z5 @6 b9 c vli_modSquare_fast(t5, t5); /* t5 = y1^4 */. c5 o* f7 {) r6 C vli_modMult_fast(Z1, Y1, Z1); /* t3 = y1*z1 = z3 */ vli_modAdd(Y1, X1, X1, curve_p); /* t2 = 2*x1^2 */ vli_modAdd(Y1, Y1, X1, curve_p); /* t2 = 3*x1^2 */0 t$ J) S7 g9 R; q; G if (vli_testBit(Y1, 0)) {+ T& C6 l7 i# B ec_word_t carry = vli_add(Y1, Y1, curve_p);0 q) A% m/ H* t0 R* e vli_rshift1(Y1); Y1[ec_WORDS - 1] |= carry << (ec_WORD_BITS - 1); } else {! G! W6 w+ z9 [4 s vli_rshift1(Y1); } /* t2 = 3/2*(x1^2) = B */ # s' t/ M2 a# C: Q vli_modSquare_fast(X1, Y1); /* t1 = B^2 */ vli_modSub(X1, X1, t4, curve_p); /* t1 = B^2 - A */ vli_modSub(X1, X1, t4, curve_p); /* t1 = B^2 - 2A = x3 */ 1 X2 u1 D( h# B+ k1 H6 G2 Y vli_modSub(t4, t4, X1, curve_p); /* t4 = A - x3 *// M1 X* C* m" i( p5 n# K$ Q# M9 ?7 P vli_modMult_fast(Y1, Y1, t4); /* t2 = B * (A - x3) */* p ~* J1 n* W$ L" s vli_modSub(Y1, Y1, t5, curve_p); /* t2 = B * (A - x3) - y1^4 = y3 */ } static void vli_modMult_fast(ec_word_t *result, const ec_word_t *left, const ec_word_t *right) { ec_word_t product[2 * ec_WORDS]; vli_mult(product, left, right); vli_mmod_fast(result, product); } static void vli_modInv(ec_word_t *result, const ec_word_t *input, const ec_word_t *mod) { ec_word_t a[ec_WORDS], b[ec_WORDS], u[ec_WORDS], v[ec_WORDS];4 q4 U) ?1 D7 J+ b6 L# E2 ] ec_word_t carry; int cmpResult;3 J/ k0 ?4 j7 L, a! J# X ? ( |. R @* T- Z. p9 t, i if (vli_isZero(input)) {6 ?8 v' L2 `+ D/ [; p vli_clear(result);. i8 E! u, ?; b: R return; } Q+ i$ I: q% n vli_set(a, input);7 ]7 i$ ?4 V9 \0 _0 }% D vli_set(b, mod);8 r }4 J/ U2 {8 M9 s1 d) _ vli_clear(u);5 J" Q8 m `: C$ J! S2 H7 b u[0] = 1; vli_clear(v); while ((cmpResult = vli_cmp(a, b)) != 0) {6 ^2 |4 i2 V( j I+ o carry = 0; if (EVEN(a)) { vli_rshift1(a);8 @! q2 K) c) a: v5 J if (!EVEN(u)) { carry = vli_add(u, u, mod);5 o- j' a; Z9 \' f8 ^ }5 K( {% Y/ X+ N" f7 M* l! m vli_rshift1(u);* z; R- \, u6 Y5 r4 S if (carry) {3 X7 Q( K6 r5 o. B6 m+ x u[ec_WORDS - 1] |= HIGH_BIT_SET; }& k# A- F9 e1 j" @1 d# c4 O& K } else if (EVEN(b)) {/ T9 W( T0 |2 k vli_rshift1(b); if (!EVEN(v)) {4 v1 m3 P5 ` n4 \& s# ] carry = vli_add(v, v, mod); } vli_rshift1(v); if (carry) { v[ec_WORDS - 1] |= HIGH_BIT_SET;) {8 z/ q$ Q$ d" e2 h }. N n' V& B, h2 N0 s5 t; I } else if (cmpResult > 0) {6 [* ?% f1 e2 [: n" U4 w/ H1 b vli_sub(a, a, b); vli_rshift1(a); if (vli_cmp(u, v) < 0) {; J" N* q! @1 B; O! t; k vli_add(u, u, mod);, i) q! G& W2 [ k- r' ]) C: k }3 z& y% w, o) s* C vli_sub(u, u, v); if (!EVEN(u)) { carry = vli_add(u, u, mod);% v# q' |1 H2 _6 s. r } vli_rshift1(u); if (carry) { u[ec_WORDS - 1] |= HIGH_BIT_SET;2 y- f n3 Q3 u* ]! @ }, w+ _. a8 `/ D6 } } else {* r. v1 }1 Z' U8 C- w* C( _" g' _ vli_sub(b, b, a); vli_rshift1(b); if (vli_cmp(v, u) < 0) {0 }0 a Z& b+ K% ?! d vli_add(v, v, mod); }8 z% B- h( J2 C3 p% v2 G vli_sub(v, v, u);& A3 O7 z9 g3 x7 l( W, T7 F: n% y if (!EVEN(v)) { carry = vli_add(v, v, mod); } vli_rshift1(v);# J& v) w+ W0 U3 g7 B if (carry) {2 k8 s. ]6 u* C. s% b: [" [0 ^5 N v[ec_WORDS - 1] |= HIGH_BIT_SET; }1 v7 V7 q+ @8 A% C4 [* R# K" t }; Y; k* V8 x/ U: V } vli_set(result, u); } . T b2 i! d; w% Q static void apply_z(ec_word_t * RESTRICT X1, ec_word_t * RESTRICT Y1,: P9 r% D$ p' Q, j' k const ec_word_t * RESTRICT Z) {! E1 r) i- K3 j) }, L/ j ec_word_t t1[ec_WORDS];" j* O/ L& f+ S# v vli_modSquare_fast(t1, Z); /* z^2 */ vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */4 G" C7 r7 a5 I ^ vli_modMult_fast(t1, t1, Z); /* z^3 */ vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */9 |, ]% u2 M) z# E- N) R }, r# l+ g. A; G$ ]% ?/ w static int vli_numBits(const ec_word_t *vli, wordcount_t max_words) { ec_word_t i; ec_word_t digit; wordcount_t num_digits = vli_numDigits(vli, max_words);8 ~4 Q" H _" u if (num_digits == 0) {6 C* M( Y9 f( D return 0;# S+ ?* a* F& @4 ` } ; _6 J9 t6 m! B0 J: s3 f4 j digit = vli[num_digits - 1];% V2 l3 I+ ~8 Z3 ]7 g for (i = 0; digit; ++i) { digit >>= 1;1 e) h0 z" t% c/ L } ! j: D `) [# J+ p7 k7 S( f2 v2 f return (((int)(num_digits - 1) << ec_WORD_BITS_SHIFT) + i); } static wordcount_t vli_numDigits(const ec_word_t *vli, wordcount_t max_words) { int i;, [5 h) A3 u+ c( i# m /* Search from the end until we find a non-zero digit. We do it in reverse because we expect that most digits will be nonzero. */6 G9 v0 x1 K- u+ V for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {- @" r* u, q& B- ` }5 r/ A: f. F% a) B 8 Y3 O0 p+ Z5 w4 R+ J& e6 D return (i + 1); } static ec_word_t vli_testBit(const ec_word_t *vli, int bit) {/ f2 n# ~7 {# [ return (vli[bit >> ec_WORD_BITS_SHIFT] & ((ec_word_t)1 << (bit & ec_WORD_BITS_MASK)));4 [6 g( Z& Z+ R7 d$ T1 Y }' o( n2 M: E2 f1 P; w static void vli_clear(ec_word_t *vli) { wordcount_t i; for (i = 0; i < ec_WORDS; ++i) {. X7 V0 Y$ W5 l# `/ u- s vli[i] = 0; } } $ M8 ?3 j1 C b. U$ \5 t static int smax(int a, int b) { return (a > b ? a : b);6 k5 V/ @# Z G1 o/ D" X5 P, K }3 S$ ~6 E( e6 }; I) o9 i: W 4 H+ H5 C$ P2 ]1 s0 G& i% \ static int vli_cmp(const ec_word_t *left, const ec_word_t *right) { int i; for (i = ec_WORDS - 1; i >= 0; --i) {7 U- g/ V/ ~* S9 V8 N2 M if (left[i] > right[i]) { return 1;. w( K) Z( l/ `2 s' I } else if (left[i] < right[i]) { return -1;3 W* p8 l8 ~' P }+ `0 M* }7 _% ^) u N } return 0; } static void vli_modAdd(ec_word_t *result, const ec_word_t *left, const ec_word_t *right, const ec_word_t *mod) {( ]8 J- l. k1 |4 T: V6 Y5 X ec_word_t carry = vli_add(result, left, right); if (carry || vli_cmp(result, mod) >= 0) vli_sub(result, result, mod); }$ c: w. o( F l* l " i& z E9 ^/ `, z6 z6 Q( m4 o& } static void vli_mmod_fast(ec_word_t *RESTRICT result, ec_word_t *RESTRICT product) { ec_word_t tmp[2 * ec_WORDS];$ w. s4 \+ W3 [4 c" f/ Z ec_word_t carry;6 N( h! \" L" \6 v6 r0 } vli_clear(tmp);5 U% G' Y/ R& l) O2 X vli_clear(tmp + ec_WORDS); / P. v+ f1 F6 U omega_mult(tmp, product + ec_WORDS); /* (Rq, q) = q * c */ % {4 ~3 G) J0 W9 V carry = vli_add(result, product, tmp); /* (C, r) = r + q */ vli_clear(product); omega_mult(product, tmp + ec_WORDS); /* Rq*c */ carry += vli_add(result, result, product); /* (C1, r) = r + Rq*c */ " p1 t- I* H/ @+ o1 z& R8 E! @ v while (carry > 0) { --carry;7 k0 j; O1 x$ h, W4 m5 Z1 | vli_sub(result, result, curve_p);) w. W9 d, H4 ~" |5 n; F3 M v( w }+ u( F" o) N S7 F- J if (vli_cmp(result, curve_p) > 0) { vli_sub(result, result, curve_p); } }3 c. | s# g+ b D5 c# S, k static void omega_mult(uint32_t * RESTRICT result, const uint32_t * RESTRICT right) { /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ uint32_t carry = 0; wordcount_t k;0 \. b( V ]4 u9 L5 [ ; g- m( \( x0 K( h- I# @& E( J for (k = 0; k < ec_WORDS; ++k) {/ x- f1 g, X, }* V1 |6 ?& Q! I uint64_t p = (uint64_t)0x3D1 * right[k] + carry;- K; g% }4 D- P" {! V result[k] = (p & 0xffffffff);3 L H. ]$ B& r+ ?- M! s% J carry = p >> 32; } result[ec_WORDS] = carry; % A" \) a% |: d; S, C% S) J1 V result[1 + ec_WORDS] = vli_add(result + 1, result + 1, right); /* add the 2^32 multiple */ }3 v) s0 N4 h5 {# y3 M , `; E: x) Z/ J: a' b4 l- }8 e0 T /*************************************************************************/' W/ K9 M# h/ M3 s. z1 y /*以下是sha256 算法 c语言实现*/ /************************************************************************/ #define SHFR(x, n) (((x) >> (n)))+ }6 N( O6 L2 K- z3 ` #define ROTR(x, n) (((x) >> (n)) | ((x) << ((sizeof(x) << 3) - (n))))8 ^3 Y* q& j5 H6 G e# a #define ROTL(x, n) (((x) << (n)) | ((x) >> ((sizeof(x) << 3) - (n))))+ H" i8 e" A& | ( X) Q0 d9 T% q #define CHX(x, y, z) (((x) & (y)) ^ (~(x) & (z))): g3 R, K! h! E: E6 X$ B #define MAJ(x, y, z) (((x) & (y)) ^ ( (x) & (z)) ^ ((y) & (z)))+ F! f b8 X; _, Y& f/ t, ` . x ] X S; Y. h2 z #define BSIG0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))% [+ ] i* e; B" ]3 U' T #define BSIG1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))% H# p# \3 d ^! O" I #define SSIG0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))* | [" |5 I- D+ k! m* U #define SSIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))8 j& {1 l, Z3 V- Z- z * v. w T1 N3 z8 r' S static uint32_t k[64] = {3 n' @% ^* w7 E! a7 a 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,8 m6 q. S- m' Y+ F Q) t1 _( R5 Q 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,4 }3 i s" J, ~. s9 v 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f27 S+ v# }* {/ O. j B7 P }; 6 M! c1 c' F L9 T. x( O int dig(const uint8_t *msg, uint32_t *h){; V! J) A D2 }+ F uint32_t w[64];, z4 U3 v- x1 f4 L; l) C } uint32_t a0, b1, c2, d3, e4, f5, g6, h7; uint32_t t1, t2; int i = 0;/ G h3 s5 a& D* L! w int j = 0;) ~8 ~5 W* a5 K8 A for (i=0; i<16; i++) { w[i] = msg[j]<<24 | msg[j+1]<<16 | msg[j+2]<<8 | msg[j+3]; j += 4;( |5 B! s7 Z' V: W } for(i=16; i<64; i++) w[i] = SSIG1(w[i-2])+w[i-7]+SSIG0(w[i-15])+w[i-16]; a0 = h[0]; b1 = h[1]; c2 = h[2]; d3 = h[3]; e4 = h[4]; f5 = h[5]; g6 = h[6]; h7 = h[7];6 Q3 Z- g1 N3 ` U- O e5 m. g7 C1 c- t: F6 \ for (i= 0; i<64; i++) { t1 = h7 + BSIG1(e4) + CHX(e4, f5, g6) + k[i] + w[i];* i& {* M. D) J1 J9 }. u% u8 e t2 = BSIG0(a0) + MAJ(a0, b1, c2);7 m4 m" x7 s7 Z7 l6 G h7 = g6;0 A3 f- q3 n: E' f0 N2 ~ g6 = f5;, D( X( l8 _% W) m' r; O; O/ { f5 = e4;/ @& {1 ^1 f7 y2 l% T) U( r- G9 \ e4 = d3 + t1; d3 = c2;+ c' [8 F9 L% C+ K ~& ]% q3 m c2 = b1; b1 = a0;3 }' o- s- |3 |" c3 d A a0 = t1 + t2;8 O2 M: Y! J- _! g }! H" m0 r' G2 G2 @% l! g$ f! ]( A3 ` 1 K) Q T2 \# x. i' e h[0] += a0; h[1] += b1;( I( y) ]7 L$ P, j h[2] += c2; Z" \7 ?4 S r' L; Y5 b# n" { h[3] += d3; h[4] += e4; h[5] += f5; h[6] += g6; h[7] += h7; ) U& `1 y4 Z* c6 X$ O _ return 0;1 @7 H! Y# j2 u% y0 Y: b }/ a( d9 G; x/ o void tobe(uint8_t *lehash,uint8_t *out,uint8_t len){& a! F* s; M4 @2 P H# X; S, ~ int i =0,j=0; for(i=0;i<len;i++) for(j=0;j<4;j++); @* z5 q" X& a out[i*4+j] = lehash[(i+1)*4-j-1]; } int sha256(const uint8_t *src, uint32_t len, uint8_t *hash){$ C7 J1 x9 j' q% ~' m2 k uint32_t h[8] = {0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19};- c& I4 w" o& K9 e+ A6 O uint32_t i;( M. {; \+ D; ]! R uint32_t bitlen = len * 8; uint32_t n = len % 64 < 56 ? len / 64 + 1 : len / 64 + 2;/ E+ F) S( f* e uint32_t new_len = 64 * n;! |. R- k! |4 I0 D! K uint8_t tmp[new_len]; //bzero(tmp, new_len);/ g3 S3 L9 C2 X# x memset(tmp,0,new_len);! Q6 Y3 \* v2 U! u; l& p memcpy(tmp, src, len); tmp[len] = 0x80; tobe((uint8_t *)&bitlen,&tmp[new_len-4],1);/ Q! m! T S* V* m7 j # G& w. Y! N4 {" { for (i=0; i<n; i++) dig(&tmp[i*64], h);' i4 e- O, H& W* {6 B) |( Q tobe((uint8_t *)h,hash,8); return 0;) x3 i+ z5 W% @' s }! h& f# f, |: V( e0 ] |
微信公众号
手机版