PC3.cc

Go to the documentation of this file.
00001 // $Id: PC3.cc 30949 2009-11-02 16:37:58Z ganis $
00002 
00003 const char *PC3CVSID = "$Id: PC3.cc 30949 2009-11-02 16:37:58Z ganis $";
00004 /* ----------------------------------------------------------------------- *
00005  *                                                                         *
00006  * PC3.cc                                                                  *
00007  *                                                                         *
00008  * C++ adaptation of PKEP implementation written by Alexander PUKALL 1991. *
00009  *                                                                         *
00010  * PKEP ( Pukall Key Exchange Protocol (c) Alexander PUKALL 1997           *
00011  *                                                                         *
00012  * Reference:  http://membres.lycos.fr/pc1/                                *
00013  *                                                                         *
00014  * Description:                                                            *
00015  * Algorithm allowing the secure exchange of a random password using the   *
00016  * PC3 cipher for random number generation based on a 160-bit seed.        *
00017  * Initialization creates private and public parts; exponentiation builds  *
00018  * the key using the received public part.                                 *
00019  *                                                                         *
00020  * Created Key length is 256 bits (32 bytes). Input random string can be   *
00021  * up to 256 bytes, but 32 or 64 should be typically enough.               *
00022  * Buffers for private and public parts should be of length kPC3SLEN       *
00023  *                                                                         *
00024  * Fro the author:                                                         *
00025  * Free code no restriction to use please include the name of the Author   *
00026  * in the final software                                                   *
00027  *                                                                         *
00028  * Adapted by G. Ganis (g.ganis@cern.ch), February 2005                    *
00029  * ----------------------------------------------------------------------- */
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #include "PC3.hh"
00035 
00036 #define kMASKLAST (0x80000000)
00037 #define kMASKFIRST (0x00000001)
00038 
00039 namespace PC3 {
00040 
00041 /* ------------------------------------------------------------------- *
00042  *         Local static auxilliary functions                           *
00043  * ------------------------------------------------------------------- */
00044 //
00045 //____________________________________________________________________
00046 static unsigned int rotl(unsigned int n, unsigned int nl)
00047 {
00048    // bit left rotation (VC++ _rotl)
00049    unsigned int i = 0;
00050 
00051    for ( i = 0; i < nl; i++) {
00052       bool bset = ((n & kMASKLAST) == kMASKLAST) ? 1 : 0;
00053       n <<= 1;
00054       if (bset)
00055          n |= kMASKFIRST;
00056       else
00057          n &= ~kMASKFIRST;
00058    }
00059    return n;
00060 }
00061 
00062 //____________________________________________________________________
00063 static unsigned long stream(unsigned int &r1, unsigned long b1)
00064 {
00065    static unsigned long a1 = 0x015a4e35;
00066 
00067    b1 = ( b1 * a1 ) + 1;
00068    r1 = rotl( (r1 + (( b1 >> 16 ) & 0x7fff)), (r1%16) );
00069 
00070    return b1;
00071 }
00072 
00073 //____________________________________________________________________
00074 static uchar pc3stream(uchar byte, unsigned long *b1,
00075                        unsigned int &r1, unsigned int key)
00076 {
00077    unsigned short d;
00078 
00079    unsigned long i = 0;
00080    for ( ; i<=(key-1); i++)
00081       b1[i] = stream(r1,b1[i]);
00082 
00083    d = byte;
00084    byte = byte^(r1 & 255);
00085    r1 += d;
00086    b1[key-1] = b1[key-1] + d;
00087 
00088    return byte;
00089 }
00090 
00091 //____________________________________________________________________
00092 unsigned int pc3init(unsigned int lngkey, uchar *code,
00093                      unsigned long *b1, unsigned int &key)
00094 {
00095    unsigned int z,y,x,i;
00096    uchar tab[kPC3MAXRPWLEN],plain;
00097    div_t reste;
00098    unsigned int r1 = 0;
00099 
00100    if (lngkey > kPC3MAXRPWLEN) lngkey = kPC3MAXRPWLEN;
00101    if (lngkey < 1) {
00102       lngkey = 1;
00103       strcpy((char *)code,"a");
00104    }
00105 
00106    x = lngkey;
00107 
00108    for ( i = 0; i < x; i++) {
00109       tab[i] = code[i];
00110    }
00111 
00112    reste = div(lngkey,2);
00113    key = reste.quot;
00114    if (reste.rem != 0) key += 1;
00115 
00116    y=0;
00117    for ( z = 0; z <= (key-1); z++) {
00118       if ( (z == (key-1)) && (reste.rem != 0) ) {
00119          b1[z]=code[y]*256;
00120       } else {
00121          b1[z] = (code[y]*256) + code[y+1];
00122          y = y+1;
00123       }
00124       y = y+1;
00125    }
00126 
00127    unsigned long ii = 0;
00128    for ( ; ii <= (key-1); ii++) {
00129       for( z = 0; z <= ii; z++)
00130          b1[ii] = stream(r1,b1[ii]);
00131    }
00132 
00133    for ( i = 0; i < x; i++) {
00134       plain = pc3stream(tab[i],b1,r1,key);
00135       tab[i] = tab[i]^plain;
00136    }
00137    i=i-1;
00138    for ( z = 1; z <= ((x+1)*10); z++) {
00139       plain = pc3stream(tab[i],b1,r1,key);
00140       tab[i] = tab[i]^plain;
00141       i++;
00142       if (i >= x) i = 0;
00143    }
00144 
00145    reste = div(lngkey,2);
00146    key   = reste.quot;
00147    if (reste.rem != 0) key += 1;
00148 
00149    for ( z = 0; z < 128; z++) {
00150       b1[z]=0;
00151    }
00152 
00153    y=0;
00154    for (z=0;z<=(key-1);z++)
00155    {
00156       if ( (z==(key-1))&&(reste.rem!=0) )
00157       {
00158          b1[z]=tab[y]*256;
00159       }
00160       else
00161       {
00162          b1[z]=(tab[y]*256)+tab[y+1];
00163          y=y+1;
00164       }
00165       y=y+1;
00166    }
00167 
00168    for (z=0;z<x;z++)
00169    {
00170       code[z]=0;
00171       tab[z]=0;
00172    }
00173 
00174    r1 = 0;
00175    for ( ii = 0; ii <= (key-1); ii++) {
00176       for ( z = 0; z <= ii; z++)
00177          b1[ii] = stream(r1,b1[ii]);
00178    }
00179    return r1;
00180 }
00181 
00182 //____________________________________________________________________
00183 static void funA(uchar *x, uchar *y, int o)
00184 {
00185    int d = 0;
00186    int v = kPC3SLEN;
00187    for( ; v--;) {
00188       d += x[v]+y[v]*o;
00189       x[v] = d;
00190       d = d>>8;
00191    }
00192 }
00193 
00194 //____________________________________________________________________
00195 static void funS(uchar *x, uchar *m)
00196 {
00197    int v = 0;
00198    for( ; (v < kPC3SLEN-1) && (x[v] == m[v]);)
00199       v++;
00200    if (x[v] >= m[v])
00201       funA(x,m,-1);
00202 }
00203 
00204 //____________________________________________________________________
00205 static void funR(uchar *x)
00206 {
00207    int d = 0;
00208    int v = 0;
00209    for ( ; v < kPC3SLEN; ) {
00210       d |= x[v];
00211       x[v++] = d/2;
00212       d = (d & 1) << 8;
00213    }
00214 }
00215 
00216 //____________________________________________________________________
00217 static void funM(uchar *x, uchar *y, uchar *m)
00218 {
00219    uchar X[1024],Y[1024];
00220 
00221    memcpy(X,x,kPC3SLEN);
00222    memcpy(Y,y,kPC3SLEN);
00223    memset(x,0,kPC3SLEN);
00224 
00225    int z = kPC3SLEN*8;
00226    for( ; z--; ) {
00227       if (X[kPC3SLEN-1] & 0x1) {
00228          funA(x,Y,1);
00229          funS(x,m);
00230       }
00231       funR(X);
00232       funA(Y,Y,1);
00233       funS(Y,m);
00234    }
00235 }
00236 
00237 //____________________________________________________________________
00238 static int createkey(uchar *rpwd, unsigned int lrpw, uchar *priv)
00239 {
00240    // Create key
00241    uchar inite[64]={0x94,0x05,0xF4,0x50,0x81,0x79,0x38,0xAB,
00242                     0x39,0x81,0x05,0x8C,0xCD,0xE8,0x04,0xDF,
00243                     0x6E,0x7C,0xAB,0x07,0x63,0xFE,0x4A,0xD7,
00244                     0x47,0x05,0x9D,0x2D,0x73,0xA9,0x38,0xBA,
00245                     0xB5,0x48,0x39,0x10,0x0A,0xD8,0xD1,0x5A,
00246                     0x9D,0x64,0x74,0xF8,0x8B,0xC5,0x3E,0x9A,
00247                     0xBF,0x27,0x55,0x9C,0x0C,0x6A,0x7E,0xD8,
00248                     0xA4,0x78,0x96,0x4C,0x96,0xBB,0x3A,0xC3};
00249    unsigned long b1[128] = {0};
00250    uchar code[kPC3MAXRPWLEN];
00251 
00252    // Check inputs
00253    if (!rpwd || (lrpw <= 0) || !priv) {
00254       return -1;
00255    }
00256 
00257    // Check length
00258    lrpw = (lrpw > (kPC3MAXRPWLEN-2)) ? (kPC3MAXRPWLEN-2) : lrpw;
00259    unsigned int i = 0;
00260    for ( ; i < lrpw; i++)
00261       code[i] = rpwd[i];
00262    //
00263    // The last two chars must be 0
00264    code[lrpw] = '\0';
00265    code[lrpw+1] = '\0';
00266 
00267    unsigned int key = 0;
00268    unsigned int r1 = pc3init(lrpw+2,code,b1,key);
00269 
00270    for ( i = 1; i < kPC3SLEN; i++)
00271       priv[i-1] = pc3stream(inite[i-1],b1,r1,key);
00272 
00273    // We are done
00274    return 0;
00275 }
00276 
00277 } // namespace PC3
00278 
00279 /* ------------------------------------------------------------------- *
00280  *                          Public functions                           *
00281  * ------------------------------------------------------------------- */
00282 //____________________________________________________________________
00283 int PC3InitDiPuk(uchar *rpwd, unsigned int lrpw, uchar *pub, uchar *priv)
00284 {
00285    // Initialize public-private key computation (Phase 1).
00286    // Input:
00287    //        rpwd    buffer containing random bits
00288    //                (max size 256 bytes; advised >= 32)
00289    //        lrpw    number of meaningful bytes in rpwd
00290    //
00291    // Output:
00292    //        priv    buffer of size kPC3SLEN containing the
00293    //                information to keep locally secure
00294    //        pub     buffer of size kPC3SLEN containing the
00295    //                information to send to the counterpart
00296    //
00297    // Return 0 if OK, -1 if buffers undefined
00298    //
00299    // nb: priv and pub buffers must be allocated by the caller.
00300    //
00301 
00302    // Check inputs
00303    if (!rpwd || (lrpw <= 0) || !pub || !priv) {
00304       return -1;
00305    }
00306 
00307    uchar prime512[64] = {
00308       0xF5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
00309       0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
00310       0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
00311       0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
00312       0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
00313       0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
00314       0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
00315       0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2A, 0x05, 0x5F
00316    };
00317    uchar e[kPC3SLEN+1] = {0};
00318    uchar m[kPC3SLEN+1] = {0};
00319    uchar g[kPC3SLEN+1] = {0};
00320 
00321    g[kPC3SLEN-1] = 3;
00322    unsigned int pr = 1;
00323    for ( ; pr < kPC3SLEN; pr++)
00324       m[pr] = prime512[pr-1];
00325 
00326    if (PC3::createkey(rpwd,lrpw,priv) < 0)
00327       return -1;
00328 
00329    for ( pr = 1; pr < kPC3SLEN; pr++)
00330       e[pr] = priv[pr-1];
00331 
00332    uchar b[kPC3SLEN] = {0};
00333    b[kPC3SLEN-1] = 1;
00334    int n = kPC3SLEN*8;
00335    for( ; n--; ) {
00336       if ((e[kPC3SLEN-1] & 0x1))
00337          PC3::funM(b,g,m);
00338       PC3::funM(g,g,m);
00339       PC3::funR(e);
00340    }
00341 
00342    // Fill the public part
00343    int i = 1;
00344    for ( ; i < kPC3SLEN; i++)
00345       pub[i-1] = b[i];
00346    pub[kPC3SLEN-1] = 0;
00347 
00348    // We are done
00349    return 0;
00350 }
00351 
00352 //____________________________________________________________________
00353 int PC3DiPukExp(uchar *pub, uchar *priv, uchar *key)
00354 {
00355    // Compute key using buffer received from counterpart(Phase 2).
00356    // Input:
00357    //        priv    buffer of size kPC3SLEN generated by a
00358    //                previous call to PC3InitDiPuk.
00359    //        pub     buffer of size kPC3SLEN containing the
00360    //                public information of the counterpart
00361    //
00362    // Output:
00363    //        key     buffer of size kPC3KEYLEN containing the
00364    //                computed random key
00365    //
00366    // Return 0 if OK, -1 if buffers undefined
00367    //
00368    // nb: all buffers must be allocated by the caller.
00369    //
00370 
00371    // Check inputs
00372    if (!key || !pub || !priv) {
00373       return -1;
00374    }
00375 
00376    uchar prime512[64] = {
00377       0xF5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
00378       0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
00379       0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
00380       0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
00381       0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
00382       0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
00383       0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
00384       0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2A, 0x05, 0x5F
00385    };
00386    uchar e[kPC3SLEN+1] = {0};
00387    uchar m[kPC3SLEN+1] = {0};
00388    uchar g[kPC3SLEN+1] = {0};
00389    uchar b[kPC3SLEN+1] = {0};
00390 
00391    unsigned int pr = 1;
00392    for ( ; pr < kPC3SLEN; pr++) {
00393       g[pr] = pub[pr-1];
00394       e[pr] = priv[pr-1];
00395       m[pr] = prime512[pr-1];
00396    }
00397    b[kPC3SLEN-1] = 1;
00398    int n = kPC3SLEN*8;
00399    for ( ; n--;) {
00400       if ((e[kPC3SLEN-1] & 0x1))
00401          PC3::funM(b,g,m);
00402       PC3::funM(g,g,m);
00403       PC3::funR(e);
00404    }
00405 
00406    // Fill the key
00407    int i = 0;
00408    for ( ; i < kPC3KEYLEN; i++)
00409       key[i] = 0;
00410    for ( i = 1; i < kPC3SLEN; i++) {
00411       key[i%kPC3KEYLEN] = key[i%kPC3KEYLEN]^b[i];
00412    }
00413 
00414    // We are done
00415    return 0;
00416 }

Generated on Tue Jul 5 14:46:32 2011 for ROOT_528-00b_version by  doxygen 1.5.1