http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/gcm.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/gcm.rs b/version22/rust/src/gcm.rs new file mode 100644 index 0000000..32e2749 --- /dev/null +++ b/version22/rust/src/gcm.rs @@ -0,0 +1,356 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +const GCM_NB:usize=4; +const GCM_ACCEPTING_HEADER:usize=0; +const GCM_ACCEPTING_CIPHER:usize=1; +const GCM_NOT_ACCEPTING_MORE:usize=2; +const GCM_FINISHED:usize=3; +const GCM_ENCRYPTING:usize=0; +const GCM_DECRYPTING:usize=1; + +use aes; +use aes::AES; + +pub struct GCM { + table: [[u32;4];128], + statex: [u8;16], + y_0: [u8;16], +// counter: usize, + lena:[u32;2], + lenc:[u32;2], + status:usize, + a:AES +} + +impl GCM { + + fn pack(b: [u8;4]) -> u32 { /* pack bytes into a 32-bit Word */ + return ((((b[0])&0xff) as u32)<<24)|((((b[1])&0xff) as u32)<<16)|((((b[2])&0xff) as u32)<<8)|(((b[3])&0xff) as u32); + } + + fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */ + let b:[u8;4]=[((a>>24)&0xff) as u8,((a>>16)&0xff) as u8,((a>>8)&0xff) as u8,(a&0xff) as u8]; + return b; + } + + fn precompute(&mut self,h: &[u8]) { + let mut b:[u8;4]=[0;4]; + let mut j=0; + for i in 0..GCM_NB { + b[0]=h[j]; b[1]=h[j+1]; b[2]=h[j+2]; b[3]=h[j+3]; + self.table[0][i]=GCM::pack(b); + j+=4; + } + for i in 1..128 { + let mut c:u32=0; + for j in 0..GCM_NB {self.table[i][j]=c|(self.table[i-1][j])>>1; c=self.table[i-1][j]<<31;} + if c != 0 {self.table[i][0]^=0xE1000000} /* irreducible polynomial */ + } + } + + fn gf2mul(&mut self) { /* gf2m mul - Z=H*X mod 2^128 */ + let mut p:[u32;4]=[0;4]; + + for i in 0..4 {p[i]=0} + let mut j:usize=8; + let mut m=0; + for i in 0..128 { + j-=1; + let mut c=((self.statex[m]>>j)&1) as u32; c= (!c) +1; + for k in 0..GCM_NB {p[k]^=self.table[i][k]&c} + if j==0 { + j=8; m+=1; + if m==16 {break} + } + } + j=0; + for i in 0..GCM_NB { + let b=GCM::unpack(p[i]); + self.statex[j]=b[0]; self.statex[j+1]=b[1]; self.statex[j+2]=b[2]; self.statex[j+3]=b[3]; + j+=4; + } + } + + fn wrap(&mut self) { /* Finish off GHASH */ + let mut f:[u32;4]=[0;4]; + let mut el:[u8;16]=[0;16]; + + /* convert lengths from bytes to bits */ + f[0]=(self.lena[0]<<3)|(self.lena[1]&0xE0000000)>>29; + f[1]=self.lena[1]<<3; + f[2]=(self.lenc[0]<<3)|(self.lenc[1]&0xE0000000)>>29; + f[3]=self.lenc[1]<<3; + let mut j=0; + for i in 0..GCM_NB { + let b=GCM::unpack(f[i]); + el[j]=b[0]; el[j+1]=b[1]; el[j+2]=b[2]; el[j+3]=b[3]; + j+=4; + } + for i in 0..16 {self.statex[i]^=el[i]} + self.gf2mul(); + } + + fn ghash(&mut self,plain: &[u8],len: usize) -> bool { + if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} + if self.status != GCM_ACCEPTING_CIPHER {return false} + + let mut j=0; + while j<len { + for i in 0..16 { + if j>=len {break} + self.statex[i]^=plain[j]; j+=1; + self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} + } + self.gf2mul(); + } + if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} + return true; + } + + /* Initialize GCM mode */ + pub fn init(&mut self,nk: usize,key: &[u8],niv: usize,iv: &[u8]) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */ + let mut h:[u8;16]=[0;16]; + + for i in 0..16 {h[i]=0; self.statex[i]=0} + + self.a=AES::new(); + + self.a.init(aes::ECB,nk,key,None); + self.a.ecb_encrypt(&mut h); /* E(K,0) */ + self.precompute(&h); + + self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0; + if niv==12 { + for i in 0..12 {self.a.f[i]=iv[i]} + let b=GCM::unpack(1); + self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* initialise IV */ + for i in 0..16 {self.y_0[i]=self.a.f[i]} + } else { + self.status=GCM_ACCEPTING_CIPHER; + self.ghash(iv,niv); /* GHASH(H,0,IV) */ + self.wrap(); + for i in 0..16 {self.a.f[i]=self.statex[i];self.y_0[i]=self.a.f[i];self.statex[i]=0} + self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0; + } + self.status=GCM_ACCEPTING_HEADER; + } + + pub fn new() -> GCM { + GCM { + table:[[0;4];128], + statex:[0;16], + y_0:[0;16], + //counter:0, + lena:[0;2], + lenc:[0;2], + status:0, + a:AES::new() + } + } + +/* Add Header data - included but not encrypted */ + pub fn add_header(&mut self,header: &[u8],len: usize) -> bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */ + if self.status != GCM_ACCEPTING_HEADER {return false} + let mut j=0; + while j<len { + for i in 0..16 { + if j>=len {break} + self.statex[i]^=header[j]; j+=1; + self.lena[1]+=1; if self.lena[1]==0 {self.lena[0]+=1} + } + self.gf2mul(); + } + if len%16 != 0 {self.status=GCM_ACCEPTING_CIPHER} + return true; + } + +/* Add Plaintext - included and encrypted */ + pub fn add_plain(&mut self,cipher: &mut [u8],plain: &[u8],len: usize) -> bool { + let mut cb:[u8;16]=[0;16]; + let mut b:[u8;4]=[0;4]; + + let mut counter: u32; + if self.status == GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} + if self.status != GCM_ACCEPTING_CIPHER {return false} + + let mut j=0; + while j<len { + b[0]=self.a.f[12]; b[1]=self.a.f[13]; b[2]=self.a.f[14]; b[3]=self.a.f[15]; + counter=GCM::pack(b); + counter+=1; + b=GCM::unpack(counter); + self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* increment counter */ + for i in 0..16 {cb[i]=self.a.f[i]} + self.a.ecb_encrypt(&mut cb); /* encrypt it */ + + for i in 0..16 { + if j>=len {break} + cipher[j]=plain[j]^cb[i]; + self.statex[i]^=cipher[j]; j+=1; + self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} + } + self.gf2mul() + } + if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} + return true; + } + +/* Add Ciphertext - decrypts to plaintext */ + pub fn add_cipher(&mut self,plain: &mut [u8],cipher: &[u8],len: usize) -> bool { + let mut cb:[u8;16]=[0;16]; + let mut b:[u8;4]=[0;4]; + + let mut counter: u32; + + if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} + if self.status != GCM_ACCEPTING_CIPHER {return false} + + let mut j=0; + while j<len { + b[0]=self.a.f[12]; b[1]=self.a.f[13]; b[2]=self.a.f[14]; b[3]=self.a.f[15]; + counter=GCM::pack(b); + counter+=1; + b=GCM::unpack(counter); + self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* increment counter */ + for i in 0..16 {cb[i]=self.a.f[i]} + self.a.ecb_encrypt(&mut cb); /* encrypt it */ + for i in 0..16 { + if j>=len {break} + let oc=cipher[j]; + plain[j]=cipher[j]^cb[i]; + self.statex[i]^=oc; j+=1; + self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} + } + self.gf2mul() + } + if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} + return true; + } + +/* Finish and extract Tag */ + pub fn finish(&mut self,extract: bool) -> [u8;16] { /* Finish off GHASH and extract tag (MAC) */ + let mut tag:[u8;16]=[0;16]; + + self.wrap(); + /* extract tag */ + if extract { + self.a.ecb_encrypt(&mut (self.y_0)); /* E(K,Y0) */ + for i in 0..16 {self.y_0[i]^=self.statex[i]} + for i in 0..16 {tag[i]=self.y_0[i];self.y_0[i]=0;self.statex[i]=0} + } + self.status=GCM_FINISHED; + self.a.end(); + return tag; + } + + pub fn hex2bytes(hex: &[u8],bin: &mut [u8]) { + let len=hex.len(); + + for i in 0..len/2 { + let mut v:u8; + let mut c = hex[2*i]; + if c >= b'0' && c <= b'9' { + v = c - b'0'; + } else if c >= b'A' && c <= b'F' { + v = c - b'A' + 10; + } else if c >= b'a' && c <= b'f' { + v = c - b'a' + 10; + } else { + v = 0; + } + v <<= 4; + c = hex[2*i + 1]; + if c >= b'0' && c <= b'9' { + v += c - b'0'; + } else if c >= b'A' && c <= b'F' { + v += c - b'A' + 10; + } else if c >= b'a' && c <= b'f' { + v += c - b'a' + 10; + } else { + v = 0; + } + bin[i] = v; + } + } + +} +/* +fn main() +{ + let kt=b"feffe9928665731c6d6a8f9467308308"; + let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; + let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2"; + let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b"; +// Tag should be 619cc5aefffe0bfa462af43c1699d050 + + let mut gcm=GCM::new(); + + let len=mt.len()/2; + let lenh=ht.len()/2; + let lenk=kt.len()/2; + let leniv=nt.len()/2; + + //let mut t:[u8;16]=[0;16]; // Tag + let mut k:[u8;16]=[0;16]; // AES Key + let mut h:[u8;64]=[0;64]; // Header - to be included in Authentication, but not encrypted + let mut n:[u8;100]=[0;100]; // IV - Initialisation vector + let mut m:[u8;100]=[0;100]; // Plaintext to be encrypted/authenticated + let mut c:[u8;100]=[0;100]; // Ciphertext + let mut p:[u8;100]=[0;100]; // Recovered Plaintext + + GCM::hex2bytes(mt,&mut m); + GCM::hex2bytes(ht,&mut h); + GCM::hex2bytes(kt,&mut k); + GCM::hex2bytes(nt,&mut n); + + println!("Plaintext="); + for i in 0..len {print!("{:02x}",m[i])} + println!(""); + + gcm.init(lenk,&k,leniv,&n); + + gcm.add_header(&h,lenh); + gcm.add_plain(&mut c,&m,len); + let mut t=gcm.finish(true); + + println!("Ciphertext="); + for i in 0..len {print!("{:02x}",c[i])} + println!(""); + + println!("Tag="); + for i in 0..16 {print!("{:02x}",t[i])} + println!(""); + + gcm.init(lenk,&k,leniv,&n); + + gcm.add_header(&h,lenh); + gcm.add_cipher(&mut p,&c,len); + t=gcm.finish(true); + + println!("Plaintext="); + for i in 0..len {print!("{:02x}",p[i])} + println!(""); + + println!("Tag="); + for i in 0..16 {print!("{:02x}",t[i])} + println!(""); + +} +*/
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/hash256.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/hash256.rs b/version22/rust/src/hash256.rs new file mode 100644 index 0000000..e2aca06 --- /dev/null +++ b/version22/rust/src/hash256.rs @@ -0,0 +1,182 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +const HASH256_H0: u32=0x6A09E667; +const HASH256_H1: u32=0xBB67AE85; +const HASH256_H2: u32=0x3C6EF372; +const HASH256_H3: u32=0xA54FF53A; +const HASH256_H4: u32=0x510E527F; +const HASH256_H5: u32=0x9B05688C; +const HASH256_H6: u32=0x1F83D9AB; +const HASH256_H7: u32=0x5BE0CD19; + +const HASH256_K : [u32;64]=[ + 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 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,0xc67178f2]; + + +pub struct HASH256 { + length: [u32;2], + h: [u32;8], + w: [u32;64] +} + +impl HASH256 { + fn s(n: u32,x: u32) -> u32 { + return ((x)>>n) | ((x)<<(32-n)); + } + fn r(n: u32,x: u32) -> u32 { + return (x)>>n; + } + + fn ch(x: u32,y: u32,z: u32) -> u32 { + return (x&y)^(!(x)&z); + } + + fn maj(x: u32,y: u32,z: u32) -> u32 { + return (x&y)^(x&z)^(y&z); + } + fn sig0(x: u32) -> u32 { + return HASH256::s(2,x)^HASH256::s(13,x)^HASH256::s(22,x); + } + + fn sig1(x: u32) -> u32 { + return HASH256::s(6,x)^HASH256::s(11,x)^HASH256::s(25,x); + } + + fn theta0(x: u32) -> u32 { + return HASH256::s(7,x)^HASH256::s(18,x)^HASH256::r(3,x); + } + + fn theta1(x: u32) -> u32 { + return HASH256::s(17,x)^HASH256::s(19,x)^HASH256::r(10,x); + } + + fn transform(&mut self) { /* basic transformation step */ + for j in 16..64 { + self.w[j]=HASH256::theta1(self.w[j-2]).wrapping_add(self.w[j-7]).wrapping_add(HASH256::theta0(self.w[j-15])).wrapping_add(self.w[j-16]); + } + let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; + let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7]; + for j in 0..64 { /* 64 times - mush it up */ + let t1=hh.wrapping_add(HASH256::sig1(e)).wrapping_add(HASH256::ch(e,f,g)).wrapping_add(HASH256_K[j]).wrapping_add(self.w[j]); + let t2=HASH256::sig0(a).wrapping_add(HASH256::maj(a,b,c)); + hh=g; g=f; f=e; + e=d.wrapping_add(t1); + d=c; + c=b; + b=a; + a=t1.wrapping_add(t2); + } + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(hh); + } + +/* Initialise Hash function */ + pub fn init(&mut self) { /* initialise */ + for i in 0..64 {self.w[i]=0} + self.length[0]=0; self.length[1]=0; + self.h[0]=HASH256_H0; + self.h[1]=HASH256_H1; + self.h[2]=HASH256_H2; + self.h[3]=HASH256_H3; + self.h[4]=HASH256_H4; + self.h[5]=HASH256_H5; + self.h[6]=HASH256_H6; + self.h[7]=HASH256_H7; + } + + pub fn new() -> HASH256 { + let mut nh=HASH256 { + length: [0;2], + h: [0;8], + w: [0;64] + }; + nh.init(); + return nh; + } + +/* process a single byte */ + pub fn process(&mut self,byt: u8) { /* process the next message byte */ + let cnt=((self.length[0]/32)%16) as usize; + self.w[cnt]<<=8; + self.w[cnt]|=(byt&0xFF) as u32; + self.length[0]+=8; + if self.length[0]==0 {self.length[1]+=1; self.length[0]=0} + if (self.length[0]%512)==0 {self.transform()} + } + +/* process an array of bytes */ + pub fn process_array(&mut self,b: &[u8]) { + for i in 0..b.len() {self.process((b[i]))} + } + +/* process a 32-bit integer */ + pub fn process_num(&mut self,n: i32) { + self.process(((n>>24)&0xff) as u8); + self.process(((n>>16)&0xff) as u8); + self.process(((n>>8)&0xff) as u8); + self.process((n&0xff) as u8); + } + +/* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8;32] { /* pad message and finish - supply digest */ + let mut digest:[u8;32]=[0;32]; + let len0=self.length[0]; + let len1=self.length[1]; + self.process(0x80); + while (self.length[0]%512)!=448 {self.process(0)} + self.w[14]=len1; + self.w[15]=len0; + self.transform(); + for i in 0..32 { /* convert to bytes */ + digest[i]=((self.h[i/4]>>(8*(3-i%4))) & 0xff) as u8; + } + self.init(); + return digest; + } +} + +//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 +/* +fn main() { + let s = String::from("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + let test = s.into_bytes(); + let mut sh=HASH256::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..32 {print!("{:02x}",digest[i])} +} +*/ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/hash384.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/hash384.rs b/version22/rust/src/hash384.rs new file mode 100644 index 0000000..0bb8546 --- /dev/null +++ b/version22/rust/src/hash384.rs @@ -0,0 +1,188 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +const HASH384_H0: u64=0xcbbb9d5dc1059ed8; +const HASH384_H1: u64=0x629a292a367cd507; +const HASH384_H2: u64=0x9159015a3070dd17; +const HASH384_H3: u64=0x152fecd8f70e5939; +const HASH384_H4: u64=0x67332667ffc00b31; +const HASH384_H5: u64=0x8eb44a8768581511; +const HASH384_H6: u64=0xdb0c2e0d64f98fa7; +const HASH384_H7: u64=0x47b5481dbefa4fa4; + +const HASH384_K : [u64;80]=[ + 0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc, + 0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118, + 0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694, + 0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65, + 0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5, + 0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70, + 0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df, + 0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b, + 0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30, + 0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec, + 0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b, + 0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178, + 0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b, + 0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]; + + +pub struct HASH384 { + length: [u64;2], + h: [u64;8], + w: [u64;80] +} + +impl HASH384 { + fn s(n: u64,x: u64) -> u64 { + return ((x)>>n) | ((x)<<(64-n)); + } + fn r(n: u64,x: u64) -> u64 { + return (x)>>n; + } + + fn ch(x: u64,y: u64,z: u64) -> u64 { + return (x&y)^(!(x)&z); + } + + fn maj(x: u64,y: u64,z: u64) -> u64 { + return (x&y)^(x&z)^(y&z); + } + + fn sig0(x: u64) -> u64 { + return HASH384::s(28,x)^HASH384::s(34,x)^HASH384::s(39,x); + } + + fn sig1(x: u64) -> u64 { + return HASH384::s(14,x)^HASH384::s(18,x)^HASH384::s(41,x); + } + + fn theta0(x: u64) -> u64 { + return HASH384::s(1,x)^HASH384::s(8,x)^HASH384::r(7,x); + } + + fn theta1(x: u64) -> u64 { + return HASH384::s(19,x)^HASH384::s(61,x)^HASH384::r(6,x); + } + + fn transform(&mut self) { /* basic transformation step */ + for j in 16..80 { + self.w[j]=HASH384::theta1(self.w[j-2])+self.w[j-7]+HASH384::theta0(self.w[j-15])+self.w[j-16]; + } + let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; + let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7]; + for j in 0..80 { /* 64 times - mush it up */ + let t1=hh+HASH384::sig1(e)+HASH384::ch(e,f,g)+HASH384_K[j]+self.w[j]; + let t2=HASH384::sig0(a)+HASH384::maj(a,b,c); + hh=g; g=f; f=e; + e=d+t1; + d=c; + c=b; + b=a; + a=t1+t2 ; + } + self.h[0]+=a; self.h[1]+=b; self.h[2]+=c; self.h[3]+=d; + self.h[4]+=e; self.h[5]+=f; self.h[6]+=g; self.h[7]+=hh; + } + +/* Initialise Hash function */ + pub fn init(&mut self) { /* initialise */ + for i in 0..64 {self.w[i]=0} + self.length[0]=0; self.length[1]=0; + self.h[0]=HASH384_H0; + self.h[1]=HASH384_H1; + self.h[2]=HASH384_H2; + self.h[3]=HASH384_H3; + self.h[4]=HASH384_H4; + self.h[5]=HASH384_H5; + self.h[6]=HASH384_H6; + self.h[7]=HASH384_H7; + } + + pub fn new() -> HASH384 { + let mut nh=HASH384 { + length: [0;2], + h: [0;8], + w: [0;80] + }; + nh.init(); + return nh; + } + +/* process a single byte */ + pub fn process(&mut self,byt: u8) { /* process the next message byte */ + let cnt=((self.length[0]/64)%16) as usize; + self.w[cnt]<<=8; + self.w[cnt]|=(byt&0xFF) as u64; + self.length[0]+=8; + if self.length[0]==0 {self.length[1]+=1; self.length[0]=0} + if (self.length[0]%1024)==0 {self.transform()} + } + +/* process an array of bytes */ + pub fn process_array(&mut self,b: &[u8]) { + for i in 0..b.len() {self.process((b[i]))} + } + +/* process a 32-bit integer */ + pub fn process_num(&mut self,n: i32) { + self.process(((n>>24)&0xff) as u8); + self.process(((n>>16)&0xff) as u8); + self.process(((n>>8)&0xff) as u8); + self.process((n&0xff) as u8); + } + +/* Generate 48-byte Hash */ + pub fn hash(&mut self) -> [u8;48] { /* pad message and finish - supply digest */ + let mut digest:[u8;48]=[0;48]; + let len0=self.length[0]; + let len1=self.length[1]; + self.process(0x80); + while (self.length[0]%1024)!=896 {self.process(0)} + self.w[14]=len1; + self.w[15]=len0; + self.transform(); + for i in 0..48 { /* convert to bytes */ + digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8; + } + self.init(); + return digest; + } +} + +//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let test = s.into_bytes(); + let mut sh=HASH384::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..48 {print!("{:02x}",digest[i])} +} */ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/hash512.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/hash512.rs b/version22/rust/src/hash512.rs new file mode 100644 index 0000000..a345781 --- /dev/null +++ b/version22/rust/src/hash512.rs @@ -0,0 +1,189 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + + +const HASH512_H0: u64=0x6a09e667f3bcc908; +const HASH512_H1: u64=0xbb67ae8584caa73b; +const HASH512_H2: u64=0x3c6ef372fe94f82b; +const HASH512_H3: u64=0xa54ff53a5f1d36f1; +const HASH512_H4: u64=0x510e527fade682d1; +const HASH512_H5: u64=0x9b05688c2b3e6c1f; +const HASH512_H6: u64=0x1f83d9abfb41bd6b; +const HASH512_H7: u64=0x5be0cd19137e2179; + +const HASH512_K : [u64;80]=[ + 0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc, + 0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118, + 0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694, + 0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65, + 0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5, + 0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70, + 0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df, + 0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b, + 0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30, + 0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec, + 0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b, + 0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178, + 0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b, + 0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]; + + +pub struct HASH512 { + length: [u64;2], + h: [u64;8], + w: [u64;80] +} + +impl HASH512 { + fn s(n: u64,x: u64) -> u64 { + return ((x)>>n) | ((x)<<(64-n)); + } + fn r(n: u64,x: u64) -> u64 { + return (x)>>n; + } + + fn ch(x: u64,y: u64,z: u64) -> u64 { + return (x&y)^(!(x)&z); + } + + fn maj(x: u64,y: u64,z: u64) -> u64 { + return (x&y)^(x&z)^(y&z); + } + + fn sig0(x: u64) -> u64 { + return HASH512::s(28,x)^HASH512::s(34,x)^HASH512::s(39,x); + } + + fn sig1(x: u64) -> u64 { + return HASH512::s(14,x)^HASH512::s(18,x)^HASH512::s(41,x); + } + + fn theta0(x: u64) -> u64 { + return HASH512::s(1,x)^HASH512::s(8,x)^HASH512::r(7,x); + } + + fn theta1(x: u64) -> u64 { + return HASH512::s(19,x)^HASH512::s(61,x)^HASH512::r(6,x); + } + + fn transform(&mut self) { /* basic transformation step */ + for j in 16..80 { + self.w[j]=HASH512::theta1(self.w[j-2])+self.w[j-7]+HASH512::theta0(self.w[j-15])+self.w[j-16]; + } + let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; + let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7]; + for j in 0..80 { /* 64 times - mush it up */ + let t1=hh+HASH512::sig1(e)+HASH512::ch(e,f,g)+HASH512_K[j]+self.w[j]; + let t2=HASH512::sig0(a)+HASH512::maj(a,b,c); + hh=g; g=f; f=e; + e=d+t1; + d=c; + c=b; + b=a; + a=t1+t2 ; + } + self.h[0]+=a; self.h[1]+=b; self.h[2]+=c; self.h[3]+=d; + self.h[4]+=e; self.h[5]+=f; self.h[6]+=g; self.h[7]+=hh; + } + +/* Initialise Hash function */ + pub fn init(&mut self) { /* initialise */ + for i in 0..64 {self.w[i]=0} + self.length[0]=0; self.length[1]=0; + self.h[0]=HASH512_H0; + self.h[1]=HASH512_H1; + self.h[2]=HASH512_H2; + self.h[3]=HASH512_H3; + self.h[4]=HASH512_H4; + self.h[5]=HASH512_H5; + self.h[6]=HASH512_H6; + self.h[7]=HASH512_H7; + } + + pub fn new() -> HASH512 { + let mut nh=HASH512 { + length: [0;2], + h: [0;8], + w: [0;80] + }; + nh.init(); + return nh; + } + +/* process a single byte */ + pub fn process(&mut self,byt: u8) { /* process the next message byte */ + let cnt=((self.length[0]/64)%16) as usize; + self.w[cnt]<<=8; + self.w[cnt]|=(byt&0xFF) as u64; + self.length[0]+=8; + if self.length[0]==0 {self.length[1]+=1; self.length[0]=0} + if (self.length[0]%1024)==0 {self.transform()} + } + +/* process an array of bytes */ + pub fn process_array(&mut self,b: &[u8]) { + for i in 0..b.len() {self.process((b[i]))} + } + +/* process a 32-bit integer */ + pub fn process_num(&mut self,n: i32) { + self.process(((n>>24)&0xff) as u8); + self.process(((n>>16)&0xff) as u8); + self.process(((n>>8)&0xff) as u8); + self.process((n&0xff) as u8); + } + +/* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8;64] { /* pad message and finish - supply digest */ + let mut digest:[u8;64]=[0;64]; + let len0=self.length[0]; + let len1=self.length[1]; + self.process(0x80); + while (self.length[0]%1024)!=896 {self.process(0)} + self.w[14]=len1; + self.w[15]=len0; + self.transform(); + for i in 0..64 { /* convert to bytes */ + digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8; + } + self.init(); + return digest; + } +} + +//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let test = s.into_bytes(); + let mut sh=HASH512::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..64 {print!("{:02x}",digest[i])} +} */ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/lib.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/lib.rs b/version22/rust/src/lib.rs new file mode 100644 index 0000000..db9c412 --- /dev/null +++ b/version22/rust/src/lib.rs @@ -0,0 +1,36 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +pub mod aes; +pub mod big; +pub mod dbig; +pub mod ecdh; +pub mod ecp; +pub mod ecp2; +pub mod ff; +pub mod fp; +pub mod fp2; +pub mod fp4; +pub mod fp12; +pub mod pair; +pub mod mpin; +pub mod rand; +pub mod hash256; +pub mod hash384; +pub mod hash512; +pub mod rsa; + +#[cfg(target_pointer_width = "32")] +#[path = "rom32.rs"] +pub mod rom; + +#[cfg(target_pointer_width = "64")] +#[path = "rom64.rs"] +pub mod rom; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + } +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/mpin.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/mpin.rs b/version22/rust/src/mpin.rs new file mode 100644 index 0000000..8644d1a --- /dev/null +++ b/version22/rust/src/mpin.rs @@ -0,0 +1,768 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +use std::time::{SystemTime}; +use std::time::UNIX_EPOCH; + +use ecp::ECP; +use fp2::FP2; +use ecp2::ECP2; +use fp4::FP4; +use fp12::FP12; +use big::BIG; +use rand::RAND; +use hash256::HASH256; +use hash384::HASH384; +use hash512::HASH512; +use pair; +use rom; + +/* MPIN API Functions */ + +/* Configure mode of operation */ + +pub const PERMITS:bool=true; +pub const PINERROR:bool=true; +pub const FULL: bool=true; +pub const SINGLE_PASS:bool=false; + +pub const EFS: usize=rom::MODBYTES as usize; +pub const EGS: usize=rom::MODBYTES as usize; +pub const PAS: usize=16; +pub const BAD_PARAMS: isize=-11; +pub const INVALID_POINT: isize=-14; +pub const WRONG_ORDER: isize=-18; +pub const BAD_PIN: isize=-19; +pub const SHA256: usize=32; +pub const SHA384: usize=48; +pub const SHA512: usize=64; + +/* Configure your PIN here */ + +pub const MAXPIN: i32=10000; /* PIN less than this */ +pub const PBLEN: i32=14; /* Number of bits in PIN */ +pub const TS: usize=10; /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */ +pub const TRAP:usize=200; /* 200 for 4 digit PIN, 2000 for 6-digit PIN - approx 2*sqrt(MAXPIN) */ + +pub const HASH_TYPE: usize=SHA256; + +#[allow(non_snake_case)] +fn hash(sha: usize,c: &mut FP4,U: &mut ECP,r: &mut [u8]) -> bool { + let mut w:[u8;EFS]=[0;EFS]; + let mut t:[u8;6*EFS]=[0;6*EFS]; + + c.geta().geta().tobytes(&mut w); for i in 0..EFS {t[i]=w[i]} + c.geta().getb().tobytes(&mut w); for i in EFS..2*EFS {t[i]=w[i-EFS]} + c.getb().geta().tobytes(&mut w); for i in 2*EFS..3*EFS {t[i]=w[i-2*EFS]} + c.getb().getb().tobytes(&mut w); for i in 3*EFS..4*EFS {t[i]=w[i-3*EFS]} + + U.getx().tobytes(&mut w); for i in 4*EFS..5*EFS {t[i]=w[i-4*EFS]} + U.gety().tobytes(&mut w); for i in 5*EFS..6*EFS {t[i]=w[i-5*EFS]} + + if sha==SHA256 { + let mut h=HASH256::new(); + h.process_array(&t); + let sh=h.hash(); + for i in 0..PAS {r[i]=sh[i]} + return true; + } + if sha==SHA384 { + let mut h=HASH384::new(); + h.process_array(&t); + let sh=h.hash(); + for i in 0..PAS {r[i]=sh[i]} + return true; + } + if sha==SHA512 { + let mut h=HASH512::new(); + h.process_array(&t); + let sh=h.hash(); + for i in 0..PAS {r[i]=sh[i]} + return true; + } + return false; + +} + +/* Hash number (optional) and string to point on curve */ + +fn hashit(sha: usize,n: usize,id: &[u8],w: &mut [u8]) -> bool { + let mut r:[u8;64]=[0;64]; + let mut didit=false; + if sha==SHA256 { + let mut h=HASH256::new(); + if n>0 {h.process_num(n as i32)} + h.process_array(id); + let hs=h.hash(); + for i in 0..sha {r[i]=hs[i];} + didit=true; + } + if sha==SHA384 { + let mut h=HASH384::new(); + if n>0 {h.process_num(n as i32)} + h.process_array(id); + let hs=h.hash(); + for i in 0..sha {r[i]=hs[i];} + didit=true; + } + if sha==SHA512 { + let mut h=HASH512::new(); + if n>0 {h.process_num(n as i32)} + h.process_array(id); + let hs=h.hash(); + for i in 0..sha {r[i]=hs[i];} + didit=true; + } + if !didit {return false} + + let rm=rom::MODBYTES as usize; + + if sha>rm { + for i in 0..rm {w[i]=r[i]} + } else { + for i in 0..sha {w[i]=r[i]} + for i in sha..rm {w[i]=0} + } + + return true; +} + +#[allow(non_snake_case)] +fn mapit(h: &[u8]) -> ECP { + let mut q=BIG::new_ints(&rom::MODULUS); + let mut x=BIG::frombytes(h); + x.rmod(&mut q); + let mut P:ECP; + + loop { + P=ECP::new_bigint(&x,0); + if !P.is_infinity() {break} + x.inc(1); x.norm(); + } + if rom::CURVE_PAIRING_TYPE!=rom::BN_CURVE { + let mut c=BIG::new_ints(&rom::CURVE_COF); + P=P.mul(&mut c); + } + return P; +} + +/* return time in slots since epoch */ +pub fn today() -> usize { + return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()/(60*1440)) as usize; +} + +/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */ +/* maps a random u to a point on the curve */ +#[allow(non_snake_case)] +fn emap(u: &BIG,cb: isize) -> ECP { + let mut P:ECP; + let mut x=BIG::new_copy(u); + let mut p=BIG::new_ints(&rom::MODULUS); + x.rmod(&mut p); + loop { + P=ECP::new_bigint(&x,cb); + if !P.is_infinity() {break} + x.inc(1); x.norm(); + } + return P; +} + +/* returns u derived from P. Random value in range 1 to return value should then be added to u */ +#[allow(non_snake_case)] +fn unmap(u: &mut BIG,P: &mut ECP) -> isize { + let s=P.gets(); + let mut R:ECP; + let mut r=0; + let x=P.getx(); + u.copy(&x); + loop { + u.dec(1); u.norm(); + r+=1; + R=ECP::new_bigint(u,s); + if !R.is_infinity() {break} + } + return r as isize; +} + +pub fn hash_id(sha: usize,id: &[u8],w: &mut [u8]) -> bool { + return hashit(sha,0,id,w); +} + +/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */ +/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */ +/* Note that u and v are indistinguisible from random strings */ +#[allow(non_snake_case)] +pub fn encoding(rng: &mut RAND,e: &mut [u8]) ->isize { + let mut t:[u8;EFS]=[0;EFS]; + + for i in 0..EFS {t[i]=e[i+1]} + let mut u=BIG::frombytes(&t); + for i in 0..EFS {t[i]=e[i+EFS+1]} + let mut v=BIG::frombytes(&t); + + let mut P=ECP::new_bigs(&u,&v); + if P.is_infinity() {return INVALID_POINT} + + let p=BIG::new_ints(&rom::MODULUS); + u=BIG::randomnum(&p,rng); + + let mut su=rng.getbyte() as isize; /*if (su<0) su=-su;*/ su%=2; + + let mut W=emap(&mut u,su); + P.sub(&mut W); + let sv=P.gets(); + let rn=unmap(&mut v,&mut P); + let mut m=rng.getbyte() as isize; /*if (m<0) m=-m;*/ m%=rn; + v.inc(m+1); + e[0]=(su+2*sv) as u8; + u.tobytes(&mut t); + for i in 0..EFS {e[i+1]=t[i]} + v.tobytes(&mut t); + for i in 0..EFS {e[i+EFS+1]=t[i]} + + return 0; +} + +#[allow(non_snake_case)] +pub fn decoding(d: &mut [u8]) -> isize { + let mut t:[u8;EFS]=[0;EFS]; + + if (d[0]&0x04)!=0 {return INVALID_POINT} + + for i in 0..EFS {t[i]=d[i+1]} + let mut u=BIG::frombytes(&t); + for i in 0..EFS {t[i]=d[i+EFS+1]} + let mut v=BIG::frombytes(&t); + + let su=(d[0]&1) as isize; + let sv=((d[0]>>1)&1) as isize; + let mut W=emap(&mut u,su); + let mut P=emap(&mut v,sv); + P.add(&mut W); + u=P.getx(); + v=P.gety(); + d[0]=0x04; + u.tobytes(&mut t); + for i in 0..EFS {d[i+1]=t[i]} + v.tobytes(&mut t); + for i in 0..EFS {d[i+EFS+1]=t[i]} + + return 0; +} + +/* R=R1+R2 in group G1 */ +#[allow(non_snake_case)] +pub fn recombine_g1(r1: &[u8],r2: &[u8],r: &mut [u8]) -> isize { + let mut P=ECP::frombytes(&r1); + let mut Q=ECP::frombytes(&r2); + + if P.is_infinity() || Q.is_infinity() {return INVALID_POINT} + + P.add(&mut Q); + + P.tobytes(r); + return 0; +} + +/* W=W1+W2 in group G2 */ +#[allow(non_snake_case)] +pub fn recombine_g2(w1: &[u8],w2: &[u8],w: &mut [u8]) -> isize { + let mut P=ECP2::frombytes(&w1); + let mut Q=ECP2::frombytes(&w2); + + if P.is_infinity() || Q.is_infinity() {return INVALID_POINT} + + P.add(&mut Q); + + P.tobytes(w); + return 0; +} + +/* create random secret S */ +pub fn random_generate(rng: &mut RAND,s: &mut [u8]) -> isize { + let r=BIG::new_ints(&rom::CURVE_ORDER); + let mut sc=BIG::randomnum(&r,rng); + if rom::AES_S>0 { + sc.mod2m(2*rom::AES_S); + } + sc.tobytes(s); + return 0; +} + +/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ +#[allow(non_snake_case)] +pub fn get_server_secret(s: &[u8],sst: &mut [u8]) -> isize { + + let mut Q=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB))); + + let mut sc=BIG::frombytes(s); + Q=pair::g2mul(&mut Q,&mut sc); + Q.tobytes(sst); + return 0; +} + +/* + W=x*H(G); + if RNG == NULL then X is passed in + if RNG != NULL the X is passed out + if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve +*/ +#[allow(non_snake_case)] +pub fn get_g1_multiple(rng: Option<&mut RAND>,typ: usize,x: &mut [u8],g: &[u8],w: &mut [u8]) -> isize { + let mut sx:BIG; + let r=BIG::new_ints(&rom::CURVE_ORDER); + + if let Some(mut rd)=rng + { + sx=BIG::randomnum(&r,rd); + if rom::AES_S>0 { + sx.mod2m(2*rom::AES_S); + } + sx.tobytes(x); + } else { + sx=BIG::frombytes(x); + } + let mut P:ECP; + + if typ==0 { + P=ECP::frombytes(g); + if P.is_infinity() {return INVALID_POINT} + } else { + P=mapit(g) + } + + + + pair::g1mul(&mut P,&mut sx).tobytes(w); + return 0; +} + + +/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ +/* CID is hashed externally */ +pub fn get_client_secret(s: &mut [u8],cid: &[u8],cst: &mut [u8]) -> isize { + return get_g1_multiple(None,1,s,cid,cst); +} + +/* Extract PIN from TOKEN for identity CID */ +#[allow(non_snake_case)] +pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize { + let mut P=ECP::frombytes(&token); + const RM:usize=rom::MODBYTES as usize; + let mut h:[u8;RM]=[0;RM]; + if P.is_infinity() {return INVALID_POINT} + hashit(sha,0,cid,&mut h); + let mut R=mapit(&h); + + R=R.pinmul(pin%MAXPIN,PBLEN); + P.sub(&mut R); + + P.tobytes(token); + + return 0; +} + +/* Functions to support M-Pin Full */ +#[allow(non_snake_case)] +pub fn precompute(token: &[u8],cid: &[u8],g1: &mut [u8],g2: &mut [u8]) -> isize { + let mut T=ECP::frombytes(&token); + if T.is_infinity() {return INVALID_POINT} + + let mut P=mapit(&cid); + + let mut Q=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB))); + + let mut g=pair::ate(&mut Q,&mut T); + g=pair::fexp(&g); + g.tobytes(g1); + + g=pair::ate(&mut Q,&mut P); + g=pair::fexp(&g); + g.tobytes(g2); + + return 0; +} + +/* Time Permit CTT=S*(date|H(CID)) where S is master secret */ +#[allow(non_snake_case)] +pub fn get_client_permit(sha: usize,date: usize,s: &[u8],cid: &[u8],ctt: &mut [u8]) ->isize { + const RM:usize=rom::MODBYTES as usize; + let mut h:[u8;RM]=[0;RM]; + hashit(sha,date,cid,&mut h); + let mut P=mapit(&h); + + let mut sc=BIG::frombytes(s); + pair::g1mul(&mut P,&mut sc).tobytes(ctt); + return 0; +} + +/* Implement step 1 on client side of MPin protocol */ +#[allow(non_snake_case)] +pub fn client_1(sha: usize,date: usize,client_id: &[u8],rng: Option<&mut RAND>,x: &mut [u8],pin: usize,token: &[u8],sec: &mut [u8],xid: Option<&mut [u8]>,xcid: Option<&mut [u8]>,permit: Option<&[u8]>) ->isize { + let r=BIG::new_ints(&rom::CURVE_ORDER); + + let mut sx:BIG; + + if let Some(mut rd)=rng + { + sx=BIG::randomnum(&r,rd); + if rom::AES_S>0 { + sx.mod2m(2*rom::AES_S); + } + sx.tobytes(x); + } else { + sx=BIG::frombytes(x); + } + + const RM:usize=rom::MODBYTES as usize; + let mut h:[u8;RM]=[0;RM]; + + hashit(sha,0,&client_id,&mut h); + let mut P=mapit(&h); + + let mut T=ECP::frombytes(&token); + if T.is_infinity() {return INVALID_POINT} + + let mut W=P.pinmul((pin as i32)%MAXPIN,PBLEN); + T.add(&mut W); + if date!=0 { + if let Some(rpermit)=permit {W=ECP::frombytes(&rpermit);} + if W.is_infinity() {return INVALID_POINT} + T.add(&mut W); + let mut h2:[u8;RM]=[0;RM]; + hashit(sha,date,&h,&mut h2); + W=mapit(&h2); + if let Some(mut rxid)=xid { + P=pair::g1mul(&mut P,&mut sx); + P.tobytes(&mut rxid); + W=pair::g1mul(&mut W,&mut sx); + P.add(&mut W); + } else { + P.add(&mut W); + P=pair::g1mul(&mut P,&mut sx); + } + if let Some(mut rxcid)=xcid {P.tobytes(&mut rxcid)} + } else { + if let Some(mut rxid)=xid { + P=pair::g1mul(&mut P,&mut sx); + P.tobytes(&mut rxid); + } + } + + T.tobytes(sec); + return 0; +} + +/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */ +#[allow(non_snake_case)] +pub fn server_1(sha: usize,date: usize,cid: &[u8],hid: &mut [u8],htid: Option<&mut [u8]>) { + const RM:usize=rom::MODBYTES as usize; + let mut h:[u8;RM]=[0;RM]; + + hashit(sha,0,cid,&mut h); + + let mut P=mapit(&h); + + P.tobytes(hid); + if date!=0 { + let mut h2:[u8;RM]=[0;RM]; + hashit(sha,date,&h,&mut h2); + let mut R=mapit(&h2); + P.add(&mut R); + if let Some(rhtid)=htid {P.tobytes(rhtid);} + } +} + +/* Implement step 2 on client side of MPin protocol */ +#[allow(non_snake_case)] +pub fn client_2(x: &[u8],y: &[u8],sec: &mut [u8]) -> isize { + let mut r=BIG::new_ints(&rom::CURVE_ORDER); + let mut P=ECP::frombytes(sec); + if P.is_infinity() {return INVALID_POINT} + + let mut px=BIG::frombytes(x); + let py=BIG::frombytes(y); + px.add(&py); + px.rmod(&mut r); + //px.rsub(r) + + P=pair::g1mul(&mut P,&mut px); + P.neg(); + P.tobytes(sec); + + return 0; +} + +/* return time since epoch */ +pub fn get_time() -> usize { + return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) as usize; +} + +/* Generate Y = H(epoch, xCID/xID) */ +pub fn get_y(sha: usize,timevalue: usize,xcid: &[u8],y: &mut [u8]) { + const RM:usize=rom::MODBYTES as usize; + let mut h:[u8;RM]=[0;RM]; + + hashit(sha,timevalue,xcid,&mut h); + + let mut sy= BIG::frombytes(&h); + let mut q=BIG::new_ints(&rom::CURVE_ORDER); + sy.rmod(&mut q); + if rom::AES_S>0 { + sy.mod2m(2*rom::AES_S); + } + sy.tobytes(y); +} + +/* Implement step 2 of MPin protocol on server side */ +#[allow(non_snake_case)] +pub fn server_2(date: usize,hid: &[u8],htid: Option<&[u8]>,y: &[u8],sst: &[u8],xid: Option<&[u8]>,xcid: Option<&[u8]>,msec: &[u8],e: Option<&mut [u8]>,f: Option<&mut [u8]>) -> isize { +// q:=NewBIGints(Modulus) + let mut Q=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB))); + + let mut sQ=ECP2::frombytes(&sst); + if sQ.is_infinity() {return INVALID_POINT} + + let mut R:ECP; + if date!=0 { + if let Some(rxcid)=xcid {R=ECP::frombytes(&rxcid);} + else {return BAD_PARAMS} + } else { + if let Some(rxid)=xid {R=ECP::frombytes(&rxid)} + else {return BAD_PARAMS} + } + if R.is_infinity() {return INVALID_POINT} + + let mut sy=BIG::frombytes(&y); + let mut P:ECP; + if date!=0 { + if let Some(rhtid)=htid {P=ECP::frombytes(&rhtid)} + else {return BAD_PARAMS} + } else { + P=ECP::frombytes(&hid); + } + + if P.is_infinity() {return INVALID_POINT} + + P=pair::g1mul(&mut P,&mut sy); + P.add(&mut R); + R=ECP::frombytes(&msec); + if R.is_infinity() {return INVALID_POINT} + + let mut g:FP12; +// FP12 g1=new FP12(0); + + g=pair::ate2(&mut Q,&mut R,&mut sQ,&mut P); + g=pair::fexp(&g); + + if !g.isunity() { + + if let Some(rxid)=xid { + if let Some(re)=e { + if let Some(rf)=f { + + g.tobytes(re); + if date!=0 { + P=ECP::frombytes(&hid); + if P.is_infinity() {return INVALID_POINT} + R=ECP::frombytes(&rxid); + if R.is_infinity() {return INVALID_POINT} + P=pair::g1mul(&mut P,&mut sy); + P.add(&mut R); + } + g=pair::ate(&mut Q,&mut P); + g=pair::fexp(&g); + g.tobytes(rf); + + } + } + } + + return BAD_PIN; + } + + return 0; +} + +/* Pollards kangaroos used to return PIN error */ +pub fn kangaroo(e: &[u8],f: &[u8]) -> isize { + let mut ge=FP12::frombytes(e); + let mut gf=FP12::frombytes(f); + let mut distance: [isize;TS]=[0;TS]; + let mut t=FP12::new_copy(&gf); + + let mut table: [FP12;TS]=[FP12::new();TS]; + let mut s:isize=1; + for m in 0..TS { + distance[m]=s; + table[m]=FP12::new_copy(&t); + s*=2; + t.usqr(); + } + t.one(); + let mut dn:isize=0; + let mut i:usize; + for _ in 0..TRAP { + i=(t.geta().geta().geta().lastbits(20)%(TS as isize)) as usize; + t.mul(&mut table[i]); + dn+=distance[i]; + } + gf.copy(&t); gf.conj(); + let mut steps:usize=0; let mut dm:isize=0; + let mut res:isize=0; + while dm-dn<MAXPIN as isize { + steps+=1; + if steps>4*TRAP {break} + i=(ge.geta().geta().geta().lastbits(20)%(TS as isize)) as usize; + ge.mul(&mut table[i]); + dm+=distance[i]; + if ge.equals(&mut t) { + res=dm-dn; + break; + } + if ge.equals(&mut gf) { + res=dn-dm; + break; + } + + } + if steps>4*TRAP || dm-dn>=MAXPIN as isize {res=0 } // Trap Failed - probable invalid token + return res; +} + +/* Hash the M-Pin transcript - new */ + +pub fn hash_all(sha: usize,hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sec: &[u8],y: &[u8],r: &[u8],w: &[u8],h: &mut[u8]) -> bool { + let mut tlen:usize=0; + const RM:usize=rom::MODBYTES as usize; + let mut t: [u8;10*RM+4]=[0;10*RM+4]; + + for i in 0 .. hid.len() {t[i]=hid[i]} + tlen+=hid.len(); + + if let Some(rxcid)=xcid { + for i in 0..rxcid.len() {t[i+tlen]=rxcid[i]} + tlen+=rxcid.len(); + } else { + for i in 0..xid.len() {t[i+tlen]=xid[i]} + tlen+=xid.len(); + } + + for i in 0..sec.len() {t[i+tlen]=sec[i]} + tlen+=sec.len(); + for i in 0..y.len() {t[i+tlen]=y[i]} + tlen+=y.len(); + for i in 0..r.len() {t[i+tlen]=r[i]} + tlen+=r.len(); + for i in 0..w.len() {t[i+tlen]=w[i]} + tlen+=w.len(); + if tlen!=10*RM+4 {return false} + + return hashit(sha,0,&t,h); +} + +/* calculate common key on client side */ +/* wCID = w.(A+AT) */ +#[allow(non_snake_case)] +pub fn client_key(sha: usize,g1: &[u8],g2: &[u8],pin: usize,r: &[u8],x: &[u8],h: &[u8],wcid: &[u8],ck: &mut [u8]) -> isize { + + let mut g1=FP12::frombytes(&g1); + let mut g2=FP12::frombytes(&g2); + let mut z=BIG::frombytes(&r); + let mut x=BIG::frombytes(&x); + let h=BIG::frombytes(&h); + + let mut W=ECP::frombytes(&wcid); + if W.is_infinity() {return INVALID_POINT} + + W=pair::g1mul(&mut W,&mut x); + + let mut f=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB)); + let mut r=BIG::new_ints(&rom::CURVE_ORDER); + let q=BIG::new_ints(&rom::MODULUS); + + z.add(&h); //new + z.rmod(&mut r); + + let mut m=BIG::new_copy(&q); + m.rmod(&mut r); + + let mut a=BIG::new_copy(&z); + a.rmod(&mut m); + + let mut b=BIG::new_copy(&z); + b.div(&mut m); + + g2.pinpow(pin as i32,PBLEN); + g1.mul(&mut g2); + + let mut c=g1.trace(); + g2.copy(&g1); + g2.frob(&mut f); + let cp=g2.trace(); + g1.conj(); + g2.mul(&mut g1); + let cpm1=g2.trace(); + g2.mul(&mut g1); + let cpm2=g2.trace(); + + c=c.xtr_pow2(&cp,&cpm1,&cpm2,&mut a,&mut b); + + hash(sha,&mut c,&mut W,ck); + + return 0 +} + +/* calculate common key on server side */ +/* Z=r.A - no time permits involved */ +#[allow(non_snake_case)] +pub fn server_key(sha: usize,z: &[u8],sst: &[u8],w: &[u8],h: &[u8],hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sk: &mut [u8]) -> isize { + let mut sQ=ECP2::frombytes(&sst); + if sQ.is_infinity() {return INVALID_POINT} + let mut R=ECP::frombytes(&z); + if R.is_infinity() {return INVALID_POINT} + let mut A=ECP::frombytes(&hid); + if A.is_infinity() {return INVALID_POINT} + + let mut U=ECP::new(); + if let Some(rxcid)=xcid { + U.copy(&ECP::frombytes(&rxcid)); + } else { + U.copy(&ECP::frombytes(&xid)); + } + + if U.is_infinity() {return INVALID_POINT} + + let mut w=BIG::frombytes(&w); + let mut h=BIG::frombytes(&h); + A=pair::g1mul(&mut A,&mut h); // new + R.add(&mut A); + + U=pair::g1mul(&mut U,&mut w); + let mut g=pair::ate(&mut sQ,&mut R); + g=pair::fexp(&g); + + let mut c=g.trace(); + + hash(sha,&mut c,&mut U,sk); + + return 0 +} + + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/pair.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/pair.rs b/version22/rust/src/pair.rs new file mode 100644 index 0000000..9e162db --- /dev/null +++ b/version22/rust/src/pair.rs @@ -0,0 +1,674 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +//mod fp; +use fp::FP; +//mod ecp; +use ecp::ECP; +//mod fp2; +use fp2::FP2; +//mod ecp2; +use ecp2::ECP2; +//mod fp4; +use fp4::FP4; +//mod fp12; +use fp12::FP12; +//mod big; +use big::BIG; +//mod dbig; +use dbig::DBIG; +//mod rand; +//mod hash256; +//mod rom; +use rom; + +#[allow(non_snake_case)] + +fn linedbl(A: &mut ECP2,qx: &mut FP,qy: &mut FP) -> FP12 { + let mut P=ECP2::new(); + + P.copy(A); + let mut zz=FP2::new_copy(&P.getpz()); + zz.sqr(); + let d=A.dbl(); + + if d<0 {return FP12::new_int(1)} + + let mut z3=FP2::new_copy(&A.getpz()); + let mut a=FP4::new(); + let mut b=FP4::new(); + let c=FP4::new(); + + let mut x=FP2::new_copy(&P.getpx()); + let mut y=FP2::new_copy(&P.getpy()); + let mut t=FP2::new_copy(&P.getpx()); + t.sqr(); + t.imul(3); + + y.sqr(); + y.dbl(); + z3.mul(&mut zz); + z3.pmul(qy); + + x.mul(&mut t); + x.sub(&y); + a.copy(&FP4::new_fp2s(&z3,&x)); + t.neg(); + zz.mul(&mut t); + zz.pmul(qx); + b.copy(&FP4::new_fp2(&zz)); + + return FP12::new_fp4s(&a,&b,&c); +} + +#[allow(non_snake_case)] +fn lineadd(A: &mut ECP2,B: &mut ECP2,qx: &mut FP,qy: &mut FP) -> FP12 { + + let mut P=ECP2::new(); + + P.copy(A); + let mut zz=FP2::new_copy(&P.getpz()); + zz.sqr(); + + let d=A.add(B); + if d<0 {return FP12::new_int(1)} + + let mut z3=FP2::new_copy(&A.getpz()); + let mut a=FP4::new(); + let mut b=FP4::new(); + let c=FP4::new(); + + if d==0 { /* Addition */ + let mut x=FP2::new_copy(&B.getpx()); + let mut y=FP2::new_copy(&B.getpy()); + let mut t=FP2::new_copy(&P.getpz()); + t.mul(&mut y); + zz.mul(&mut t); + + let mut ny=FP2::new_copy(&P.getpy()); ny.neg(); + zz.add(&ny); + z3.pmul(qy); + t.mul(&mut P.getpx()); + x.mul(&mut ny); + t.add(&x); + a.copy(&FP4::new_fp2s(&z3,&t)); + zz.neg(); + zz.pmul(qx); + b.copy(&FP4::new_fp2(&zz)); + } else { /* Doubling */ + let mut x=FP2::new_copy(&P.getpx()); + let mut y=FP2::new_copy(&P.getpy()); + let mut t=FP2::new_copy(&P.getpx()); + t.sqr(); + t.imul(3); + + y.sqr(); + y.dbl(); + z3.mul(&mut zz); + z3.pmul(qy); + + x.mul(&mut t); + x.sub(&y); + a.copy(&FP4::new_fp2s(&z3,&x)); + t.neg(); + zz.mul(&mut t); + zz.pmul(qx); + b.copy(&FP4::new_fp2(&zz)); + } + return FP12::new_fp4s(&a,&b,&c); +} + +#[allow(non_snake_case)] +/* Optimal R-ate pairing */ +pub fn ate(P: & mut ECP2,Q: &mut ECP) -> FP12 { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB)); + let x = BIG::new_ints(&rom::CURVE_BNX); + let mut n = BIG::new_copy(&x); + let mut K = ECP2::new(); + + + if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE { + n.pmul(6); n.dec(2); + } else {n.copy(&x)} + + n.norm(); + P.affine(); + Q.affine(); + let mut qx=FP::new_copy(&Q.getpx()); + let mut qy=FP::new_copy(&Q.getpy()); + + let mut A=ECP2::new(); + let mut r=FP12::new_int(1); + + A.copy(&P); + let nb=n.nbits(); + + for i in (1..nb-1).rev() { + let mut lv=linedbl(&mut A,&mut qx,&mut qy); + r.smul(&mut lv); + if n.bit(i)==1 { + + lv=lineadd(&mut A,P,&mut qx,&mut qy); + + r.smul(&mut lv); + } + r.sqr(); + } + + let mut lv=linedbl(&mut A,&mut qx,&mut qy); + r.smul(&mut lv); + + if n.parity()==1 { + lv=lineadd(&mut A,P,&mut qx,&mut qy); + r.smul(&mut lv); + } + +/* R-ate fixup required for BN curves */ + + if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE { + r.conj(); + K.copy(&P); + K.frob(&mut f); + A.neg(); + lv=lineadd(&mut A,&mut K,&mut qx,&mut qy); + r.smul(&mut lv); + K.frob(&mut f); + K.neg(); + lv=lineadd(&mut A,&mut K,&mut qx,&mut qy); + r.smul(&mut lv); + } + + return r; +} + +#[allow(non_snake_case)] +/* Optimal R-ate double pairing e(P,Q).e(R,S) */ +pub fn ate2(P: &mut ECP2,Q: &mut ECP,R: &mut ECP2,S: &mut ECP) -> FP12 { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB)); + let x = BIG::new_ints(&rom::CURVE_BNX); + let mut n = BIG::new_copy(&x); + let mut K = ECP2::new(); + + + if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE { + n.pmul(6); n.dec(2); + } else {n.copy(&x)} + + n.norm(); + P.affine(); + Q.affine(); + R.affine(); + S.affine(); + + let mut qx=FP::new_copy(&Q.getpx()); + let mut qy=FP::new_copy(&Q.getpy()); + + let mut sx=FP::new_copy(&S.getpx()); + let mut sy=FP::new_copy(&S.getpy()); + + let mut A=ECP2::new(); + let mut B=ECP2::new(); + let mut r=FP12::new_int(1); + + A.copy(&P); + B.copy(&R); + let nb=n.nbits(); + + for i in (1..nb-1).rev() { + let mut lv=linedbl(&mut A,&mut qx,&mut qy); + r.smul(&mut lv); + lv=linedbl(&mut B,&mut sx,&mut sy); + r.smul(&mut lv); + + if n.bit(i)==1 { + lv=lineadd(&mut A,P,&mut qx,&mut qy); + r.smul(&mut lv); + lv=lineadd(&mut B,R,&mut sx,&mut sy); + r.smul(&mut lv); + } + r.sqr(); + } + + let mut lv=linedbl(&mut A,&mut qx,&mut qy); + r.smul(&mut lv); + lv=linedbl(&mut B,&mut sx,&mut sy); + r.smul(&mut lv); + if n.parity()==1 { + lv=lineadd(&mut A,P,&mut qx,&mut qy); + r.smul(&mut lv); + lv=lineadd(&mut B,R,&mut sx,&mut sy); + r.smul(&mut lv); + } + +/* R-ate fixup */ + if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE { + r.conj(); + K.copy(&P); + K.frob(&mut f); + A.neg(); + lv=lineadd(&mut A,&mut K,&mut qx,&mut qy); + r.smul(&mut lv); + K.frob(&mut f); + K.neg(); + lv=lineadd(&mut A,&mut K,&mut qx,&mut qy); + r.smul(&mut lv); + + K.copy(&R); + K.frob(&mut f); + B.neg(); + lv=lineadd(&mut B,&mut K,&mut sx,&mut sy); + r.smul(&mut lv); + K.frob(&mut f); + K.neg(); + lv=lineadd(&mut B,&mut K,&mut sx,&mut sy); + r.smul(&mut lv); + } + + return r; +} + +/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ +pub fn fexp(m: &FP12) -> FP12 { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB)); + let mut x = BIG::new_ints(&rom::CURVE_BNX); + let mut r=FP12::new_copy(m); + +/* Easy part of final exp */ + let mut lv=FP12::new_copy(&r); + lv.inverse(); + r.conj(); + + r.mul(&mut lv); + lv.copy(&r); + r.frob(&mut f); + r.frob(&mut f); + r.mul(&mut lv); +/* Hard part of final exp */ + if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE { + lv.copy(&r); + lv.frob(&mut f); + let mut x0=FP12::new_copy(&lv); + x0.frob(&mut f); + lv.mul(&mut r); + x0.mul(&mut lv); + x0.frob(&mut f); + let mut x1=FP12::new_copy(&r); + x1.conj(); + let mut x4=r.pow(&mut x); + + let mut x3=FP12::new_copy(&x4); + x3.frob(&mut f); + + let mut x2=x4.pow(&mut x); + + let mut x5=FP12::new_copy(&x2); x5.conj(); + lv=x2.pow(&mut x); + + x2.frob(&mut f); + r.copy(&x2); r.conj(); + + x4.mul(&mut r); + x2.frob(&mut f); + + r.copy(&lv); + r.frob(&mut f); + lv.mul(&mut r); + + lv.usqr(); + lv.mul(&mut x4); + lv.mul(&mut x5); + r.copy(&x3); + r.mul(&mut x5); + r.mul(&mut lv); + lv.mul(&mut x2); + r.usqr(); + r.mul(&mut lv); + r.usqr(); + lv.copy(&r); + lv.mul(&mut x1); + r.mul(&mut x0); + lv.usqr(); + r.mul(&mut lv); + r.reduce(); + } else { + +// Ghamman & Fouotsa Method + + let mut y0=FP12::new_copy(&r); y0.usqr(); + let mut y1=y0.pow(&mut x); + x.fshr(1); let mut y2=y1.pow(&mut x); x.fshl(1); + let mut y3=FP12::new_copy(&r); y3.conj(); + y1.mul(&mut y3); + + y1.conj(); + y1.mul(&mut y2); + + y2=y1.pow(&mut x); + + y3=y2.pow(&mut x); + y1.conj(); + y3.mul(&mut y1); + + y1.conj(); + y1.frob(&mut f); y1.frob(&mut f); y1.frob(&mut f); + y2.frob(&mut f); y2.frob(&mut f); + y1.mul(&mut y2); + + y2=y3.pow(&mut x); + y2.mul(&mut y0); + y2.mul(&mut r); + + y1.mul(&mut y2); + y2.copy(&y3); y2.frob(&mut f); + y1.mul(&mut y2); + r.copy(&y1); + r.reduce(); + + +/* + let mut x0=FP12::new_copy(&r); + let mut x1=FP12::new_copy(&r); + lv.copy(&r); lv.frob(&mut f); + let mut x3=FP12::new_copy(&lv); x3.conj(); x1.mul(&mut x3); + lv.frob(&mut f); lv.frob(&mut f); + x1.mul(&mut lv); + + r=r.pow(&mut x); //r=r.pow(x); + x3.copy(&r); x3.conj(); x1.mul(&mut x3); + lv.copy(&r); lv.frob(&mut f); + x0.mul(&mut lv); + lv.frob(&mut f); + x1.mul(&mut lv); + lv.frob(&mut f); + x3.copy(&lv); x3.conj(); x0.mul(&mut x3); + + r=r.pow(&mut x); + x0.mul(&mut r); + lv.copy(&r); lv.frob(&mut f); lv.frob(&mut f); + x3.copy(&lv); x3.conj(); x0.mul(&mut x3); + lv.frob(&mut f); + x1.mul(&mut lv); + + r=r.pow(&mut x); + lv.copy(&r); lv.frob(&mut f); + x3.copy(&lv); x3.conj(); x0.mul(&mut x3); + lv.frob(&mut f); + x1.mul(&mut lv); + + r=r.pow(&mut x); + x3.copy(&r); x3.conj(); x0.mul(&mut x3); + lv.copy(&r); lv.frob(&mut f); + x1.mul(&mut lv); + + r=r.pow(&mut x); + x1.mul(&mut r); + + x0.usqr(); + x0.mul(&mut x1); + r.copy(&x0); + r.reduce(); */ + } + return r; +} + +#[allow(non_snake_case)] +/* GLV method */ +fn glv(e: &mut BIG) -> [BIG;2] { + let mut u:[BIG;2]=[BIG::new(),BIG::new()]; + if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE { + let mut t=BIG::new(); + let q=BIG::new_ints(&rom::CURVE_ORDER); + let mut v:[BIG;2]=[BIG::new(),BIG::new()]; + + for i in 0..2 { + t.copy(&BIG::new_ints(&rom::CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); + let mut d:DBIG = BIG::mul(&mut t,e); + v[i].copy(&d.div(&q)); + } + u[0].copy(&e); + for i in 0..2 { + for j in 0..2 { + t=BIG::new_ints(&rom::CURVE_SB[j][i]); + t=BIG::modmul(&mut v[j],&mut t,&q); + u[i].add(&q); + u[i].sub(&t); + u[i].rmod(&q); + } + } + } else { + let q=BIG::new_ints(&rom::CURVE_ORDER); + let x=BIG::new_ints(&rom::CURVE_BNX); + let x2=BIG::smul(&x,&x); + u[0].copy(&e); + u[0].rmod(&x2); + u[1].copy(&e); + u[1].div(&x2); + u[1].rsub(&q); + } + return u; +} + +#[allow(non_snake_case)] +/* Galbraith & Scott Method */ +pub fn gs(e: &mut BIG) -> [BIG;4] { + let mut u:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()]; + if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE { + let mut t=BIG::new(); + let q=BIG::new_ints(&rom::CURVE_ORDER); + + let mut v:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()]; + for i in 0..4 { + t.copy(&BIG::new_ints(&rom::CURVE_WB[i])); + let mut d:DBIG=BIG::mul(&mut t,e); + v[i].copy(&d.div(&q)); + } + u[0].copy(&e); + for i in 0..4 { + for j in 0..4 { + t=BIG::new_ints(&rom::CURVE_BB[j][i]); + t=BIG::modmul(&mut v[j],&mut t,&q); + u[i].add(&q); + u[i].sub(&t); + u[i].rmod(&q); + } + } + } else { + let x=BIG::new_ints(&rom::CURVE_BNX); + let mut w=BIG::new_copy(&e); + for i in 0..4 { + u[i].copy(&w); + u[i].rmod(&x); + w.div(&x); + } + } + return u; +} + +#[allow(non_snake_case)] +/* Multiply P by e in group G1 */ +pub fn g1mul(P: &mut ECP,e: &mut BIG) -> ECP { + let mut R=ECP::new(); + if rom::USE_GLV { + P.affine(); + R.copy(P); + let mut Q=ECP::new(); + Q.copy(P); + let q=BIG::new_ints(&rom::CURVE_ORDER); + let mut cru=FP::new_big(&BIG::new_ints(&rom::CURVE_CRU)); + let mut u=glv(e); + Q.mulx(&mut cru); + + let mut np=u[0].nbits(); + let mut t:BIG=BIG::modneg(&mut u[0],&q); + let mut nn=t.nbits(); + if nn<np { + u[0].copy(&t); + R.neg(); + } + + np=u[1].nbits(); + t=BIG::modneg(&mut u[1],&q); + nn=t.nbits(); + if nn<np { + u[1].copy(&t); + Q.neg(); + } + + R=R.mul2(&u[0],&mut Q,&u[1]); + + } else { + R=P.mul(e); + } + return R; +} + +#[allow(non_snake_case)] +/* Multiply P by e in group G2 */ +pub fn g2mul(P: &mut ECP2,e: &mut BIG) -> ECP2 { + let mut R=ECP2::new(); + if rom::USE_GS_G2 { + let mut Q:[ECP2;4]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()]; + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB)); + let q=BIG::new_ints(&rom::CURVE_ORDER); + let mut u=gs(e); + let mut T=ECP2::new(); + + let mut t=BIG::new(); + P.affine(); + Q[0].copy(&P); + for i in 1..4 { + T.copy(&Q[i-1]); + Q[i].copy(&T); + Q[i].frob(&mut f); + } + for i in 0..4 { + let np=u[i].nbits(); + t.copy(&BIG::modneg(&mut u[i],&q)); + let nn=t.nbits(); + if nn<np { + u[i].copy(&t); + Q[i].neg(); + } + } + + R.copy(&ECP2::mul4(&mut Q,&u)); + + } else { + R.copy(&P.mul(e)); + } + return R; +} + +/* f=f^e */ +/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */ +pub fn gtpow(d: &mut FP12,e: &mut BIG) -> FP12 { + let mut r=FP12::new(); + if rom::USE_GS_GT { + let mut g:[FP12;4]=[FP12::new(),FP12::new(),FP12::new(),FP12::new()]; + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB)); + let q=BIG::new_ints(&rom::CURVE_ORDER); + let mut t=BIG::new(); + let mut u=gs(e); + let mut w=FP12::new(); + + g[0].copy(&d); + for i in 1..4 { + w.copy(&g[i-1]); + g[i].copy(&w); + g[i].frob(&mut f); + } + for i in 0..4 { + let np=u[i].nbits(); + t.copy(&BIG::modneg(&mut u[i],&q)); + let nn=t.nbits(); + if nn<np { + u[i].copy(&t); + g[i].conj(); + } + } + r.copy(&FP12::pow4(&mut g,&u)); + } else { + r.copy(&d.pow(e)); + } + return r; +} + +/* +#[allow(non_snake_case)] +fn main() +{ + let mut Q=ECP::new_bigs(&BIG::new_ints(&rom::CURVE_GX),&BIG::new_ints(&rom::CURVE_GY)); + let mut P=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB))); + + let mut r=BIG::new_ints(&rom::CURVE_ORDER); + + println!("P= {}",P.tostring()); + println!("Q= {}",Q.tostring()); + + //m:=NewBIGint(17) + + let mut e=ate(&mut P,&mut Q); + println!("\ne= {}",e.tostring()); + + e=fexp(&e); + + for i in 1..10 { + e=ate(&mut P,&mut Q); + e=fexp(&e); + } + + + // e=GTpow(e,m); + + println!("\ne= {}",e.tostring()); + + + fmt.Printf("\n"); + GLV:=glv(r) + + fmt.Printf("GLV[0]= "+GLV[0].toString()) + fmt.Printf("\n") + + fmt.Printf("GLV[0]= "+GLV[1].toString()) + fmt.Printf("\n") + + G:=NewECP(); G.copy(Q) + R:=NewECP2(); R.copy(P) + + + e=ate(R,Q) + e=fexp(e) + + e=GTpow(e,xa) + fmt.Printf("\ne= "+e.toString()); + fmt.Printf("\n") + + R=G2mul(R,xa) + e=ate(R,G) + e=fexp(e) + + fmt.Printf("\ne= "+e.toString()) + fmt.Printf("\n") + + G=G1mul(G,xa) + e=ate(P,G) + e=fexp(e) + fmt.Printf("\ne= "+e.toString()) + fmt.Printf("\n") +}*/ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/rand.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/rand.rs b/version22/rust/src/rand.rs new file mode 100644 index 0000000..5cf79ac --- /dev/null +++ b/version22/rust/src/rand.rs @@ -0,0 +1,147 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +//mod hash256; + +use hash256::HASH256; + +const RAND_NK: usize=21; +const RAND_NJ: usize=6; +const RAND_NV: usize=8; + +pub struct RAND { + ira: [u32;RAND_NK], /* random number... */ + rndptr: usize, + borrow: u32, + pool_ptr: usize, + pool: [u8;32] +} + +impl RAND { + + pub fn new() -> RAND { + RAND { + ira: [0;RAND_NK], + rndptr:0, + borrow: 0, + pool_ptr:0, + pool:[0;32] + } + } + + pub fn clean(&mut self) { + self.pool_ptr=0; self.rndptr=0; + for i in 0..32 {self.pool[i]=0} + for i in 0..RAND_NK {self.ira[i]=0} + self.borrow=0; + } + + fn sbrand(&mut self) -> u32 { /* Marsaglia & Zaman random number generator */ + self.rndptr+=1; + if self.rndptr<RAND_NK {return self.ira[self.rndptr]} + self.rndptr=0; + let mut k=RAND_NK-RAND_NJ; + for i in 0..RAND_NK { /* calculate next NK values */ + if k==RAND_NK {k=0} + let t=self.ira[k]; + let pdiff=t.wrapping_sub(self.ira[i]).wrapping_sub(self.borrow); + if pdiff<t {self.borrow=0} + if pdiff>t {self.borrow=1} + self.ira[i]=pdiff; + k+=1; + } + return self.ira[0]; + } + + fn sirand(&mut self,seed: u32) { + let mut m: u32=1; + let mut sd=seed; + self.borrow=0; + self.rndptr=0; + self.ira[0]^=sd; + for i in 1..RAND_NK { /* fill initialisation vector */ + let inn=(RAND_NV*i)%RAND_NK; + self.ira[inn]^=m; /* note XOR */ + let t=m; + m=sd.wrapping_sub(m); + sd=t; + } + for _ in 0..10000 {self.sbrand();} /* "warm-up" & stir the generator */ + } + + fn fill_pool(&mut self) { + let mut sh=HASH256::new(); + for _ in 0..128 {sh.process((self.sbrand()&0xff) as u8)} + let w=sh.hash(); + for i in 0..32 {self.pool[i]=w[i]} + self.pool_ptr=0; + } + + fn pack(b: [u8;4]) -> u32 { /* pack 4 bytes into a 32-bit Word */ + return ((((b[3] as u32))&0xff)<<24)|(((b[2] as u32)&0xff)<<16)|(((b[1] as u32)&0xff)<<8)|((b[0] as u32)&0xff); + } + +/* Initialize RNG with some real entropy from some external source */ + pub fn seed(&mut self,rawlen: usize,raw: &[u8]) { /* initialise from at least 128 byte string of raw random entropy */ + let mut b: [u8;4]=[0;4]; + let mut sh=HASH256::new(); + self.pool_ptr=0; + + for i in 0..RAND_NK {self.ira[i]=0} + if rawlen>0 { + for i in 0..rawlen { + sh.process(raw[i]); + } + let digest=sh.hash(); + +/* initialise PRNG from distilled randomness */ + + for i in 0..8 { + b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]; + self.sirand(RAND::pack(b)); + } + } + self.fill_pool(); + } + +/* get random byte */ + pub fn getbyte(&mut self) -> u8 { + let r=self.pool[self.pool_ptr]; + self.pool_ptr+=1; + if self.pool_ptr>=32 {self.fill_pool()} + return (r&0xff) as u8; + } +} + +/* test main program */ +/* +fn main() { + let mut raw : [u8;100]=[0;100]; + let mut rng=RAND::new(); + + rng.clean(); + for i in 0..100 {raw[i]=i as u8} + + rng.seed(100,&raw); + + for _ in 0..1000 { + print!("{:03} ",rng.getbyte()); + } +} +*/
