Skip to content

Commit 9f77259

Browse files
committed
Port @floodyberry's poly1305-donna-16 for nacl-fast.
1 parent f65f2a4 commit 9f77259

File tree

4 files changed

+171
-59
lines changed

4 files changed

+171
-59
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -383,14 +383,16 @@ JavaScript port:
383383
* [Dmitry Chestnykh](http://github.com/dchest) (ported xsalsa20, poly1305, curve25519)
384384
* [Devi Mandiri](https://github.com/devi) (ported curve25519, ed25519, sha512)
385385

386-
Original authors of [NaCl](http://nacl.cr.yp.to) and [TweetNaCl](http://tweetnacl.cr.yp.to)
386+
Original authors of [NaCl](http://nacl.cr.yp.to), [TweetNaCl](http://tweetnacl.cr.yp.to)
387+
and [Poly1305-donna](https://github.com/floodyberry/poly1305-donna)
387388
(who are *not* responsible for any errors in this implementation):
388389

389390
* [Daniel J. Bernstein](http://cr.yp.to/djb.html)
390391
* Wesley Janssen
391392
* [Tanja Lange](http://hyperelliptic.org/tanja)
392393
* [Peter Schwabe](http://www.cryptojedi.org/users/peter/)
393394
* [Matthew Dempsky](https://github.com/mdempsky)
395+
* [Andrew Moon](https://github.com/floodyberry)
394396

395397
Contributors have dedicated their work to the public domain.
396398

nacl-fast.js

+165-57
Original file line numberDiff line numberDiff line change
@@ -385,70 +385,178 @@ function crypto_stream_xor(c,cpos,m,mpos,d,n,k) {
385385
return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,sn,s);
386386
}
387387

388-
function add1305(h, c) {
389-
var j, u = 0;
390-
for (j = 0; j < 17; j++) {
391-
u = (u + ((h[j] + c[j]) | 0)) | 0;
392-
h[j] = u & 255;
393-
u >>>= 8;
388+
/*
389+
* Port of Andrew Moon's Poly1305-donna-16. Public domain.
390+
* https://github.com/floodyberry/poly1305-donna
391+
*/
392+
393+
function U8TO16(p, i) { return (p[i] & 0xff) | ((p[i+1] & 0xff) << 8); }
394+
function U16TO8(p, i, v) { p[i] = (v >>> 0) & 0xff; p[i+1] = (v >>> 8) & 0xff; }
395+
396+
var poly1305 = function(key) {
397+
this.buffer = new Uint8Array(16);
398+
this.r = new Uint16Array(10);
399+
this.h = new Uint16Array(10);
400+
this.pad = new Uint16Array(8);
401+
this.leftover = 0;
402+
this.fin = 0;
403+
404+
var i, t0, t1, t2, t3, t4, t5, t6, t7;
405+
406+
t0 = U8TO16(key, 0); this.r[0] = ( t0 ) & 0x1fff;
407+
t1 = U8TO16(key, 2); this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
408+
t2 = U8TO16(key, 4); this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;
409+
t3 = U8TO16(key, 6); this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
410+
t4 = U8TO16(key, 8); this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;
411+
this.r[5] = ((t4 >>> 1)) & 0x1ffe;
412+
t5 = U8TO16(key,10); this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
413+
t6 = U8TO16(key,12); this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;
414+
t7 = U8TO16(key,14); this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
415+
this.r[9] = ((t7 >>> 5)) & 0x007f;
416+
417+
for (i = 0; i < 8; i++) this.pad[i] = U8TO16(key, 16 + (2 * i));
418+
}
419+
420+
poly1305.prototype.blocks = function(m, mpos, bytes) {
421+
var hibit = this.fin ? 0 : (1 << 11);
422+
var t0, t1, t2, t3, t4, t5, t6, t7;
423+
var d = new Uint32Array(10);
424+
var c, i, j;
425+
426+
while (bytes >= 16) {
427+
t0 = U8TO16(m, mpos+0); this.h[0] += ( t0 ) & 0x1fff;
428+
t1 = U8TO16(m, mpos+2); this.h[1] += ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
429+
t2 = U8TO16(m, mpos+4); this.h[2] += ((t1 >>> 10) | (t2 << 6)) & 0x1fff;
430+
t3 = U8TO16(m, mpos+6); this.h[3] += ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
431+
t4 = U8TO16(m, mpos+8); this.h[4] += ((t3 >>> 4) | (t4 << 12)) & 0x1fff;
432+
this.h[5] += ((t4 >>> 1)) & 0x1fff;
433+
t5 = U8TO16(m, mpos+10); this.h[6] += ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
434+
t6 = U8TO16(m, mpos+12); this.h[7] += ((t5 >>> 11) | (t6 << 5)) & 0x1fff;
435+
t7 = U8TO16(m, mpos+14); this.h[8] += ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
436+
this.h[9] += ((t7 >>> 5)) | hibit;
437+
438+
for (i = 0, c = 0; i < 10; i++) {
439+
d[i] = c;
440+
for (j = 0; j < 10; j++) {
441+
d[i] += this.h[j] * ((j <= i) ? this.r[i - j] : (5 * this.r[i + 10 - j]));
442+
if (j === 4) {
443+
c = (d[i] >>> 13);
444+
d[i] &= 0x1fff;
445+
}
446+
}
447+
c += (d[i] >>> 13);
448+
d[i] &= 0x1fff;
449+
}
450+
c = (((c << 2) + c)) | 0;
451+
c = (c + d[0]) | 0;
452+
d[0] = c & 0x1fff;
453+
c = (c >>> 13);
454+
d[1] += c;
455+
456+
for (i = 0; i < 10; i++) this.h[i] = d[i];
457+
458+
mpos += 16;
459+
bytes -= 16;
394460
}
395461
}
396462

397-
var minusp = new Uint32Array([
398-
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252
399-
]);
463+
poly1305.prototype.finish = function(mac, macpos) {
464+
var g = new Uint16Array(10);
465+
var c, mask, f, i;
400466

401-
function crypto_onetimeauth(out, outpos, m, mpos, n, k) {
402-
var s, i, j, u;
403-
var x = new Uint32Array(17), r = new Uint32Array(17),
404-
h = new Uint32Array(17), c = new Uint32Array(17),
405-
g = new Uint32Array(17);
406-
for (j = 0; j < 17; j++) r[j]=h[j]=0;
407-
for (j = 0; j < 16; j++) r[j]=k[j];
408-
r[3]&=15;
409-
r[4]&=252;
410-
r[7]&=15;
411-
r[8]&=252;
412-
r[11]&=15;
413-
r[12]&=252;
414-
r[15]&=15;
415-
416-
while (n > 0) {
417-
for (j = 0; j < 17; j++) c[j] = 0;
418-
for (j = 0;(j < 16) && (j < n);++j) c[j] = m[mpos+j];
419-
c[j] = 1;
420-
mpos += j; n -= j;
421-
add1305(h,c);
422-
for (i = 0; i < 17; i++) {
423-
x[i] = 0;
424-
for (j = 0; j < 17; j++) x[i] = (x[i] + (h[j] * ((j <= i) ? r[i - j] : ((320 * r[i + 17 - j])|0))) | 0) | 0;
425-
}
426-
for (i = 0; i < 17; i++) h[i] = x[i];
427-
u = 0;
428-
for (j = 0; j < 16; j++) {
429-
u = (u + h[j]) | 0;
430-
h[j] = u & 255;
431-
u >>>= 8;
432-
}
433-
u = (u + h[16]) | 0; h[16] = u & 3;
434-
u = (5 * (u >>> 2)) | 0;
435-
for (j = 0; j < 16; j++) {
436-
u = (u + h[j]) | 0;
437-
h[j] = u & 255;
438-
u >>>= 8;
439-
}
440-
u = (u + h[16]) | 0; h[16] = u;
467+
if (this.leftover) {
468+
i = this.leftover;
469+
this.buffer[i++] = 1;
470+
for (; i < 16; i++) this.buffer[i] = 0;
471+
this.fin = 1;
472+
this.blocks(this.buffer, 0, 16);
473+
}
474+
475+
c = this.h[1] >>> 13;
476+
this.h[1] &= 0x1fff;
477+
for (i = 2; i < 10; i++) {
478+
this.h[i] += c;
479+
c = this.h[i] >>> 13;
480+
this.h[i] &= 0x1fff;
481+
}
482+
this.h[0] += (c * 5);
483+
c = this.h[0] >>> 13;
484+
this.h[0] &= 0x1fff;
485+
this.h[1] += c;
486+
c = this.h[1] >>> 13;
487+
this.h[1] &= 0x1fff;
488+
this.h[2] += c;
489+
490+
g[0] = this.h[0] + 5;
491+
c = g[0] >>> 13;
492+
g[0] &= 0x1fff;
493+
for (i = 1; i < 10; i++) {
494+
g[i] = this.h[i] + c;
495+
c = g[i] >>> 13;
496+
g[i] &= 0x1fff;
497+
}
498+
g[9] -= (1 << 13);
499+
500+
mask = (g[9] >>> ((2 * 8) - 1)) - 1;
501+
for (i = 0; i < 10; i++) g[i] &= mask;
502+
mask = ~mask;
503+
for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i];
504+
505+
this.h[0] = ((this.h[0] ) | (this.h[1] << 13) ) & 0xffff;
506+
this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10) ) & 0xffff;
507+
this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7) ) & 0xffff;
508+
this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4) ) & 0xffff;
509+
this.h[4] = ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff;
510+
this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11) ) & 0xffff;
511+
this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8) ) & 0xffff;
512+
this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5) ) & 0xffff;
513+
514+
f = this.h[0] + this.pad[0];
515+
this.h[0] = f & 0xffff;
516+
for (i = 1; i < 8; i++) {
517+
f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0;
518+
this.h[i] = f & 0xffff;
519+
}
520+
521+
for (i = 0; i < 8; i++) U16TO8(mac, macpos + i*2, this.h[i]);
522+
}
523+
524+
poly1305.prototype.update = function(m, mpos, bytes) {
525+
var i, want;
526+
527+
if (this.leftover) {
528+
want = (16 - this.leftover);
529+
if (want > bytes)
530+
want = bytes;
531+
for (i = 0; i < want; i++)
532+
this.buffer[this.leftover + i] = m[mpos+i];
533+
bytes -= want;
534+
mpos += want;
535+
this.leftover += want;
536+
if (this.leftover < 16)
537+
return;
538+
this.blocks(buffer, 0, 16);
539+
this.leftover = 0;
441540
}
442541

443-
for (j = 0; j < 17; j++) g[j] = h[j];
444-
add1305(h,minusp);
445-
s = (-(h[16] >>> 7) | 0);
446-
for (j = 0; j < 17; j++) h[j] ^= s & (g[j] ^ h[j]);
542+
if (bytes >= 16) {
543+
want = (bytes & ~(16 - 1));
544+
this.blocks(m, mpos, want);
545+
mpos += want;
546+
bytes -= want;
547+
}
447548

448-
for (j = 0; j < 16; j++) c[j] = k[j + 16];
449-
c[16] = 0;
450-
add1305(h,c);
451-
for (j = 0; j < 16; j++) out[outpos+j] = h[j];
549+
if (bytes) {
550+
for (i = 0; i < bytes; i++)
551+
this.buffer[this.leftover + i] = m[mpos+i];
552+
this.leftover += bytes;
553+
}
554+
}
555+
556+
function crypto_onetimeauth(out, outpos, m, mpos, n, k) {
557+
var s = new poly1305(k);
558+
s.update(m, mpos, n);
559+
s.finish(out, outpos);
452560
return 0;
453561
}
454562

0 commit comments

Comments
 (0)