void wots_sign(unsigned char sig[WOTS_L*HASH_BYTES], const unsigned char msg[HASH_BYTES], const unsigned char sk[SEED_BYTES], const unsigned char masks[(WOTS_W-1)*HASH_BYTES]) { int basew[WOTS_L],i,c=0; #if WOTS_W != 16 #error "Implementation specialized for WOTS_W == 16" #endif for(i=0;i<WOTS_L1;i+=2) { basew[i] = msg[i/2] & 0xf; basew[i+1] = msg[i/2] >> 4; c += WOTS_W - 1 - basew[i]; c += WOTS_W - 1 - basew[i+1]; } for( ;i<WOTS_L;i++) { basew[i] = c & 0xf; c >>= 4; } expand_seed(sig, sk); /* for(i=0;i<WOTS_L;i++) gen_chain(sig+i*HASH_BYTES, sig+i*HASH_BYTES, masks, basew[i]); */ gen_partialchains(sig,sig,masks,basew); }
void wots_pkgen(unsigned char pk[WOTS_L*HASH_BYTES], const unsigned char sk[SEED_BYTES], const unsigned char masks[(WOTS_W-1)*HASH_BYTES]) { expand_seed(pk, sk); gen_fullchains(pk, masks); }
int horst_sign(unsigned char *sig, unsigned char pk[HASH_BYTES], unsigned long long *sigbytes, const unsigned char *m, unsigned long long mlen, const unsigned char seed[SEED_BYTES], const unsigned char masks[2*HORST_LOGT*HASH_BYTES], const unsigned char m_hash[MSGHASH_BYTES]) { unsigned char sk[HORST_T*HORST_SKBYTES]; unsigned int idx; int i,j,k; int sigpos = 0; unsigned char tree[(2*HORST_T-1)*HASH_BYTES]; /* replace by something more memory-efficient? */ expand_seed(sk, seed); // Build the whole tree and save it #if HORST_SKBYTES != HASH_BYTES #error "Need to have HORST_SKBYTES == HASH_BYTES" #endif // Generate pk leaves non parallel //for(i=0;i<HORST_T;i++) // hash_n_n(tree+(HORST_T-1+i)*HASH_BYTES, sk+i*HORST_SKBYTES); // Generate pk leaves parallel for(i=0;i<HORST_T;i+=8) hash_n_n_8x(tree+(HORST_T-1+i)*HASH_BYTES, sk+i*HORST_SKBYTES); // Build tree // Hash from level 0 to 1 loop_hash_2n_n_mask_8x(tree+(32767)*HASH_BYTES,tree+(65535)*HASH_BYTES,4096,masks); // Hash from level 1 to 2 loop_hash_2n_n_mask_8x(tree+(16383)*HASH_BYTES,tree+(32767)*HASH_BYTES,2048,masks+2*HASH_BYTES); // Hash from level 2 to 3 loop_hash_2n_n_mask_8x(tree+(8191)*HASH_BYTES,tree+(16383)*HASH_BYTES,1024,masks+4*HASH_BYTES); // Hash from level 3 to 4 loop_hash_2n_n_mask_8x(tree+(4095)*HASH_BYTES,tree+(8191)*HASH_BYTES,512,masks+6*HASH_BYTES); // Hash from level 4 to 5 loop_hash_2n_n_mask_8x(tree+(2047)*HASH_BYTES,tree+(4095)*HASH_BYTES,256,masks+8*HASH_BYTES); // Hash from level 5 to 6 loop_hash_2n_n_mask_8x(tree+(1023)*HASH_BYTES,tree+(2047)*HASH_BYTES,128,masks+10*HASH_BYTES); // Hash from level 6 to 7 loop_hash_2n_n_mask_8x(tree+(511)*HASH_BYTES,tree+(1023)*HASH_BYTES,64,masks+12*HASH_BYTES); // Hash from level 7 to 8 loop_hash_2n_n_mask_8x(tree+(255)*HASH_BYTES,tree+(511)*HASH_BYTES,32,masks+14*HASH_BYTES); // Hash from level 8 to 9 loop_hash_2n_n_mask_8x(tree+(127)*HASH_BYTES,tree+(255)*HASH_BYTES,16,masks+16*HASH_BYTES); // Hash from level 9 to 10 loop_hash_2n_n_mask_8x(tree+(63)*HASH_BYTES,tree+(127)*HASH_BYTES,8,masks+18*HASH_BYTES); // Hash from level 10 to 11 loop_hash_2n_n_mask_8x(tree+(31)*HASH_BYTES,tree+(63)*HASH_BYTES,4,masks+20*HASH_BYTES); // Hash from level 11 to 12 loop_hash_2n_n_mask_8x(tree+(15)*HASH_BYTES,tree+(31)*HASH_BYTES,2,masks+22*HASH_BYTES); // Hash from level 12 to 13 loop_hash_2n_n_mask_8x(tree+(7)*HASH_BYTES,tree+(15)*HASH_BYTES,1,masks+24*HASH_BYTES); // Hash from level 13 to 14 for(j=0;j<4;j++) hash_2n_n_mask(tree+(3+j)*HASH_BYTES,tree+(7+2*j)*HASH_BYTES,masks+26*HASH_BYTES); // Hash from level 14 to 15 for(j=0;j<2;j++) hash_2n_n_mask(tree+(1+j)*HASH_BYTES,tree+(3+2*j)*HASH_BYTES,masks+28*HASH_BYTES); // Hash from level 15 to 16 hash_2n_n_mask(tree+0*HASH_BYTES,tree+1*HASH_BYTES,masks+30*HASH_BYTES); #if HORST_K != (MSGHASH_BYTES/2) #error "Need to have HORST_K == (MSGHASH_BYTES/2)" #endif // First write 64 hashes from level 10 to the signature for(j=63*HASH_BYTES;j<127*HASH_BYTES;j++) sig[sigpos++] = tree[j]; // Signature consists of HORST_K parts; each part of secret key and HORST_LOGT-4 auth-path hashes for(i=0;i<HORST_K;i++) { idx = m_hash[2*i] + (m_hash[2*i+1]<<8); for(k=0;k<HORST_SKBYTES;k++) sig[sigpos++] = sk[idx*HORST_SKBYTES+k]; idx += (HORST_T-1); for(j=0;j<HORST_LOGT-6;j++) { idx = (idx&1)?idx+1:idx-1; // neighbor node for(k=0;k<HASH_BYTES;k++) sig[sigpos++] = tree[idx*HASH_BYTES+k]; idx = (idx-1)/2; // parent node } } for(i=0;i<HASH_BYTES;i++) pk[i] = tree[i]; *sigbytes = HORST_SIGBYTES; return 0; }