Module: Nuckle::Internals::Poly1305
- Defined in:
- lib/nuckle/internals/poly1305.rb
Overview
Poly1305 one-time message authenticator.
Reference: cr.yp.to/mac/poly1305-20050329.pdf
RFC 8439 Section 2.5
Constant Summary collapse
- P =
(1 << 130) - 5
- R_CLAMP =
Clamp mask for r (clear specific bits per spec)
0x0ffffffc0ffffffc0ffffffc0fffffff- MASK128 =
(1 << 128) - 1
Class Method Summary collapse
-
.int_to_le_bytes(n) ⇒ Object
Write a 128-bit integer as 16 little-endian bytes.
-
.le_bytes_to_int(bytes, offset, length) ⇒ Object
Read little-endian integer from a string at offset, length bytes.
-
.mac(key, message) ⇒ String
Compute Poly1305 MAC.
Class Method Details
.int_to_le_bytes(n) ⇒ Object
Write a 128-bit integer as 16 little-endian bytes.
65 66 67 |
# File 'lib/nuckle/internals/poly1305.rb', line 65 def int_to_le_bytes(n) [n & 0xFFFFFFFFFFFFFFFF, (n >> 64) & 0xFFFFFFFFFFFFFFFF].pack("Q<2") end |
.le_bytes_to_int(bytes, offset, length) ⇒ Object
Read little-endian integer from a string at offset, length bytes.
53 54 55 56 57 58 59 60 61 62 |
# File 'lib/nuckle/internals/poly1305.rb', line 53 def le_bytes_to_int(bytes, offset, length) if length == 16 lo, hi = bytes.unpack("@#{offset}Q<2") lo | (hi << 64) else n = 0 length.times { |i| n |= bytes.getbyte(offset + i) << (8 * i) } n end end |
.mac(key, message) ⇒ String
Compute Poly1305 MAC.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/nuckle/internals/poly1305.rb', line 26 def mac(key, ) r = le_bytes_to_int(key, 0, 16) & R_CLAMP s = le_bytes_to_int(key, 16, 16) h = 0 msg = .b len = msg.bytesize off = 0 while off < len remaining = len - off take = remaining < 16 ? remaining : 16 block = le_bytes_to_int(msg, off, take) # Add high bit (2^(8*take)) to mark block as non-zero-padded block |= 1 << (take * 8) h = ((h + block) * r) % P off += take end # Final: (h + s) mod 2^128 tag = (h + s) & MASK128 int_to_le_bytes(tag) end |