/* @(#)root/auth:$Id$ */ /* Author: Martin Nicolay 22/11/1988 */ /****************************************************************************** Copyright (C) 2006 Martin Nicolay This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ******************************************************************************/ /******************************************************************************* * * * Simple RSA public key code. * * Adaptation in library for ROOT by G. Ganis, July 2003 * * (gerardo.ganis@cern.ch) * * * *******************************************************************************/ #include #include #include #include #include #include "rsaaux.h" #include "rsalib.h" static int g_clear_siz; /* clear-text blocksize */ static int g_enc_siz; /* encoded blocksize */ /* g_clear_siz < g_enc_siz */ int gLog = 0; int kMAXT = 100; rsa_NUMBER rsa_genprim(int len, int prob) { rsa_NUMBER a_three,a_four; rsa_NUMBER prim; int i; a_add( &a_one, &a_two, &a_three ); a_add( &a_two, &a_two, &a_four ); /* This is done elsewhere to allow different initialization of rand seed (GGa - Sep 15, 2003) */ /* init_rnd(); */ do { gen_number( len, &prim ); } while ( !prim.n_len ); a_mult( &prim, &a_two, &prim ); a_mult( &prim, &a_three, &prim ); a_add( &prim, &a_one, &prim ); for (i=1 ;; i++) { if (p_prim( &prim, prob )) break; if (i % 2) a_add( &prim, &a_four, &prim ); else a_add( &prim, &a_two, &prim ); } return prim; } int rsa_genrsa(rsa_NUMBER p1, rsa_NUMBER p2, rsa_NUMBER *n, rsa_NUMBER *e, rsa_NUMBER *d) { rsa_NUMBER phi, *max_p; int len; int ii, jj; if ( !a_cmp( &p1, &p2) ) return 1; if (a_cmp( &p1, &p2) > 0) max_p = &p1; else max_p = &p2; a_mult( &p1, &p2, n ); a_sub( &p1, &a_one, &phi ); a_sub( &p2, &a_one, e ); a_mult( &phi, e, &phi ); len = n_bitlen( &phi ); len = ( len + 3) / 4; a_assign( &p1, &phi ); a_sub( &p1, &a_one, &p1 ); /* This is done elsewhere to allow different initialization of rand seed (GGa - Sep 15, 2003) */ /* init_rnd(); */ ii = 0; do { ii++; jj = 0; do { jj++; gen_number( len, d ); } while (((a_cmp( d, max_p) <= 0 || a_cmp( d, &p1) >= 0)) && jj < kMAXT); a_ggt( d, &phi, e ); } while ( a_cmp( e, &a_one) && ii < kMAXT); if (ii >= kMAXT || jj >= kMAXT) return 2; inv( d, &phi, e ); return 0; } int rsa_encode_size(rsa_NUMBER n) { // Returns length unit block of output return ( n_bitlen( &n) + 7) / 8; } int rsa_encode(char *bufin, int lin, rsa_NUMBER n, rsa_NUMBER e) { /* Encodes plain string in 'bufin' (output in 'bufin') Returns length of encoded string (key validity is not checked) */ char buf[ rsa_STRLEN*2 ]; char bufout[ rsa_STRLEN*2 ]; int i, j, lout; char *pout; g_enc_siz = ( n_bitlen( &n) + 7) / 8; g_clear_siz = g_enc_siz -1; m_init( &n, rsa_NUM0P ); pout = bufout; lout = 0; for ( i = 0; i < lin; i += g_clear_siz) { memcpy(buf,bufin+i,g_clear_siz); j = ((lin-i) < g_clear_siz) ? lin-i : g_clear_siz; memset(buf+j,0,(g_enc_siz-j)); do_crypt( buf, buf, g_enc_siz, &e ); memcpy(pout,buf,g_enc_siz); pout += g_enc_siz; lout += g_enc_siz; } memcpy(bufin,bufout,lout); return lout; } int rsa_decode(char *bufin, int lin, rsa_NUMBER n, rsa_NUMBER e) { /* Decodes string in 'bufin' (output in 'bufin') Returns length of plaintext string (key validity is not checked) */ char buf[ rsa_STRLEN*2 ]; char bufout[ rsa_STRLEN*2 ]; int i, lout; char *pout; g_enc_siz = ( n_bitlen( &n) + 7) / 8; g_clear_siz = g_enc_siz -1; m_init( &n, rsa_NUM0P ); pout = bufout; lout = 0; for ( i = 0; i < lin; i += g_enc_siz) { memcpy(buf,bufin+i,g_enc_siz); do_crypt( buf, buf, g_enc_siz, &e ); memcpy(pout,buf,g_clear_siz); pout += g_clear_siz; lout += g_clear_siz; } memcpy(bufin,bufout,lout); return lout; } /******************************************************************************* * * * nio.c * * * ********************************************************************************/ /* * rsa_NUMBER io */ /* * Funktionen * * int num_sput( n, s, l) * rsa_NUMBER *n; * char s[l]; * schreibt *n als Hex-Zahl in s * * int num_fput( n, f ) * rsa_NUMBER *n; * FILE *f; * schreibt *n als Hex-Zahl in File f * * int num_sget( n, s ) * rsa_NUMBER *n; * char *s; * liest Hex-Zahl s in *n ein * * int num_fget( n, f ) * rsa_NUMBER *n; * FILE *f; * liest eine Hex-Zahl von f in *n ein * */ static const char *gHEX="0123456789ABCDEF"; static const char *ghex="0123456789abcdef"; static rsa_NUMBER gbits[9]; static rsa_NUMBER gint16[16]; static int ginit = 0; void num_init() { int i; if (ginit) return; a_assign( &gbits[0], &a_one ); for ( i=1; i<9; i++) a_add( &gbits[i-1], &gbits[i-1], &gbits[i] ); a_assign( &gint16[0], &a_one ); for ( i=1; i<16; i++) a_add( &gint16[i-1], &a_one, &gint16[i] ); ginit = 1; } int rsa_num_sput(rsa_NUMBER *n, char *s, int l) { #if rsa_MAXINT == ( (1 << rsa_MAXBIT) - 1 ) rsa_INT *p; int bi,ab,i; long b; int first = 1; bi = rsa_MAXBIT * n->n_len; ab = 4 - (bi + 3) % 4 -1; p = &n->n_part[n->n_len -1]; if ( (bi+3) / 4 >= l ) return(EOF); b = 0; while (bi) { b <<= (rsa_MAXBIT); b |= (unsigned long)*p--; bi -= rsa_MAXBIT; ab += rsa_MAXBIT; while (ab >= 4) { i = (b >> (ab - 4)); b &= ( 1L << (ab - 4)) -1L; ab -= 4; if (first && !i) continue; first = 0; *s++ = gHEX[ i ]; } } if (b) abort(); *s = '\0'; return (0); #else rsa_NUMBER r,q; int i,b,p,len,low,high; char *np; if (! ginit) num_init(); a_assign( &q, n); len = l; np = s + l; for (; q.n_len && len > 1; len --) { a_div( &q, &gbits[4], &q, &r ); for (p=8, b=0, i=3; i >= 0; i--, p /= 2) { if ( a_cmp( &r, &gbits[i]) >= 0) { a_sub( &r, &gbits[i], &r ); b += p; } } *--np = gHEX[ b ]; } if (q.n_len) return(EOF); l -= len; len = l; for (; l--; ) *s++ = *np++; *s = '\0'; return (0); #endif } int rsa_num_fput(rsa_NUMBER *n, FILE *f) { int j; char *np; char n_print[ rsa_STRLEN + 1 ]; if ( rsa_num_sput( n, n_print, sizeof( n_print) ) == EOF ) return(EOF); for (j=0, np=n_print; *np ; np++, j++) { if (j==64) { fputs("\n",f); j = 0; } putc((int)*np,f); } if (j) putc('\n',f); return(0); } int rsa_num_sget(rsa_NUMBER *n, char *s) { #if rsa_MAXINT == ( (1 << rsa_MAXBIT) - 1 ) rsa_INT *p; const char *hp; int bi,ab,i; long b; int first = 1; bi = 4 * strlen(s); ab = rsa_MAXBIT - (bi + rsa_MAXBIT -1) % rsa_MAXBIT -1; i = (bi + rsa_MAXBIT-1) / rsa_MAXBIT; p = &n->n_part[ i -1 ]; n->n_len = i; if ( i > rsa_MAXLEN ) return(EOF); b = 0; while (bi > 0) { if ( (hp = strchr( gHEX, *s )) ) i = hp - gHEX; else if ((hp = strchr( ghex, *s )) ) i = hp - ghex; else return(EOF); s++; b <<= 4; b |= (unsigned long)i; bi -= 4; ab += 4; while (ab >= rsa_MAXBIT) { i = (b >> (ab - rsa_MAXBIT)); b &= ( 1L << (ab - rsa_MAXBIT)) -1L; ab -= rsa_MAXBIT; if (first && !i) { p--; n->n_len--; } else { first = 0; *p-- = i; } } } if (b) abort(); *s = '\0'; return (0); #else char *p; int i,c; if (! ginit) num_init(); n->n_len = 0; while ( (c = *s++ & 0xFF)) { if ( p= strchr( gHEX, c) ) i = p - gHEX; else if ( p= strchr( ghex, c) ) i = p - ghex; else return(EOF); a_mult( n, &gbits[4], n ); if (i) a_add( n, &gint16[i-1], n ); } return(0); #endif } int rsa_num_fget(rsa_NUMBER *n, FILE *f) { int j,c; char *np; char n_print[ rsa_STRLEN + 1 ]; np = n_print; j = sizeof(n_print); while ( (c=getc(f)) != EOF && ( isxdigit(c) || isspace(c)) ) { if (isspace(c)) continue; if (! --j) return(EOF); *np++ = (char)c; } *np = '\0'; if (c != EOF) ungetc(c,f); if ( rsa_num_sget( n, n_print) == EOF ) return( EOF ); return(0); } int rsa_cmp(rsa_NUMBER *c1, rsa_NUMBER *c2) { int l; /* bei verschiedener Laenge klar*/ if ( (l=c1->n_len) != c2->n_len) return( l - c2->n_len); /* vergleiche als arrays */ return( n_cmp( c1->n_part, c2->n_part, l) ); } void rsa_assign(rsa_NUMBER *d, rsa_NUMBER *s) { int l; if (s == d) /* nichts zu kopieren */ return; if ((l=s->n_len)) memcpy( d->n_part, s->n_part, sizeof(rsa_INT)*l); d->n_len = l; }