Browse Source

Some initial approach to Poly1305

Marcin Krzyżanowski 11 years ago
parent
commit
028f5caa44
1 changed files with 114 additions and 3 deletions
  1. 114 3
      CryptoSwift/Poly1305.swift

+ 114 - 3
CryptoSwift/Poly1305.swift

@@ -13,7 +13,8 @@
 import Foundation
 
 class Poly1305 {
-
+    let blockSize = 16
+    
     var r:[Byte] = [Byte](count: 17, repeatedValue: 0)
     var h:[Byte] = [Byte](count: 17, repeatedValue: 0)
     var pad:[Byte] = [Byte](count: 17, repeatedValue: 0)
@@ -24,12 +25,15 @@ class Poly1305 {
             return;
         }
         
-        for i in 0...15 {
+        for i in 0..<17 {
             h[i] = 0
+        }
+
+        for i in 0..<16 {
             r[i] = key[i] & 0x0f
             pad[i] = key[i + 16]
         }
-        
+
         h[16] = 0
         r[16] = 0
         pad[16] = 0
@@ -37,6 +41,113 @@ class Poly1305 {
         final = 0
     }
     
+    func add(inout h:[Byte], c:[Byte]) -> Bool {
+        if (h.count != 17 && c.count != 17) {
+            return false
+        }
+        
+        var u:Byte = 0
+        for i in 0..<h.count {
+            u = u &+ h[i] &+ c[i]
+            h[0] = u
+            u >>= 8
+        }
+        return true
+    }
+    
+    func squeeze(inout h:[Byte], hr:[UInt32]) -> Bool {
+        if (h.count != 17 && hr.count != 17) {
+            return false
+        }
+
+        var u:UInt32 = 0
+
+        for i in 0..<16 {
+            u = u &+ hr[i];
+            h[i] = Byte(u) & 0xff;
+            u >>= 8;
+        }
+        
+        u = u &+ hr[16]
+        h[16] = Byte(u) & 0x03
+        u >>= 2
+        u += (u << 2); /* u *= 5; */
+        for i in 0..<16 {
+            u = u &+ UInt32(h[i])
+            h[i] = Byte(u) & 0xff
+            u >>= 8
+        }
+        h[16] = h[16] &+ Byte(u);
+        
+        return true
+    }
+    
+    func freeze(inout h:[Byte]) -> Bool {
+        if (h.count != 17) {
+            return false
+        }
+        
+        let minusp:[Byte] = [0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc]
+        var horig:[Byte] = [Byte](count: 17, repeatedValue: 0)
+        
+        /* compute h + -p */
+        for i in 0..<17 {
+            horig[i] = h[i]
+        }
+        
+        add(&h, c: minusp)
+        
+        /* select h if h < p, or h + -p if h >= p */
+        let bits:[Bit] = (h[16] >> 7).bits()
+        let invertedBits = bits.map({ (bit) -> Bit in
+            return bit.inverted()
+        })
+        
+        let negative = Byte(bits: invertedBits)
+        for i in 0..<17 {
+            h[i] ^= negative & (horig[i] ^ h[i]);
+        }
+        
+        return true;
+    }
+    
+    func blocks(m:[Byte]) {
+        var mPos = 0
+        var bytes = m.count
+        let hibit = final ^ 1 // 1 <<128
+        
+        while (bytes >= Int(blockSize)) {
+            var hr:[UInt32] = [UInt32](count: 17, repeatedValue: 0)
+            var u:UInt32 = 0
+            var c:[Byte] = [Byte](count: 17, repeatedValue: 0)
+            
+            /* h += m */
+            for i in 0..<16 {
+                c[i] = m[mPos + i]
+            }
+            c[16] = hibit
+            add(&h,c: c)
+            
+            /* h *= r */
+            for i in 0..<17 {
+                u = 0
+                for j in 0...i {
+                    u = u + UInt32(UInt16(h[j])) * UInt32(r[i - j]) // u += (unsigned short)st->h[j] * st->r[i - j];
+                }
+                for j in (i+1)..<17 {
+                    var v:UInt32 = UInt32(UInt16(h[j])) * UInt32(r[i + 17 - j])  // unsigned long v = (unsigned short)st->h[j] * st->r[i + 17 - j];
+                    v = ((v &<< 8) &+ (v &<< 6))
+                    u = u &+ v
+                }
+                hr[i] = u
+            }
+            squeeze(&h, hr: hr)
+            
+            mPos += blockSize //m = m + blockSize
+            bytes -= blockSize
+        }
+    }
+    
     deinit {
         for i in 0...(r.count) {
             r[i] = 0