精华内容
下载资源
问答
  • rsa算法c语言实现

    2019-03-08 23:50:14
    为了在网上找一个rsa算法的代码实现想当不容易,索性就自己实现了一下。代码是RSA加密算法C语言版本,大数代码是从网上找到的,性能上还有些问题,需要进一步优化。不过拿来做测试用是足够了。C++版本的可靠性、性能...
  • RSA算法C语言实现(附实验报告,代码,程序)
  • RSA算法C语言实现

    万次阅读 2016-05-12 11:32:07
    RSA算法C语言实现一、源文件三个rsa.h , rsa.c , main.c//rsa.h #include #define MAX_NUM 63001 #define MAX_PRIME 251//! 返回代码 #define OK 100 #define ERROR_NOEACHPRIME 101 #define ERROR_NOPUBLICKEY 102...

    RSA算法C语言实现

    一、源文件三个rsa.h , rsa.c , main.c

    //rsa.h
    #include <stdio.h>
    #define MAX_NUM 63001
    #define MAX_PRIME 251
    
    //! 返回代码
    #define OK 100
    #define ERROR_NOEACHPRIME 101
    #define ERROR_NOPUBLICKEY 102
    #define ERROR_GENERROR 103
    
    unsigned int MakePrivatedKeyd( unsigned int uiP, unsigned int uiQ );
    unsigned int GetPrivateKeyd( unsigned int iWhich );
    unsigned int MakePairkey( unsigned int uiP, unsigned int uiQ, unsigned int uiD );
    unsigned int GetPairKey( unsigned int &d, unsigned int &e );
    void rsa_encrypt( int n, int e, char *mw, int iLength, int *&cw );
    void rsa_decrypt( int n, int d, int *&cw, int cLength, char *mw );
    void outputkey();
    
    //rsa.c
    #include "rsa.h"
    //! 保存私钥d集合
    struct pKeyset
    {
    unsigned int set[ MAX_NUM ];
    unsigned int size;
    }pset;
    
    //! 保存公、私钥对
    struct pPairkey
    {
    unsigned int d;
    unsigned int e;
    unsigned int n;
    }pairkey;
    
    // 名称:isPrime
    // 功能:判断两个数是否互质
    //  参数:m: 数a; n: 数b
    // 返回:m、n互质返回true; 否则返回false
    
    bool isPrime( unsigned int m, unsigned int n )
    {
    unsigned int i=0;
    bool Flag = true;
    
    if( m<2 || n<2 )
    return false;
    
    unsigned int tem = ( m > n ) ? n : m;
    for( i=2; i<=tem && Flag; i++ )
    {
    bool mFlag = true;
    bool nFlag = true;
    if( m % i == 0 )
    mFlag = false;
    if( n % i == 0 )
    nFlag = false;
    if( !mFlag && !nFlag )
    Flag = false;
    }
    if( Flag )
    return true;
    else
    return false;
    }
    
    // 名称:MakePrivatedKeyd
    // 功能:由素数Q、Q生成私钥d
    //  参数:uiP: 素数P; uiQ: 素数Q
    // 返回:私钥d
    
    unsigned int MakePrivatedKeyd( unsigned int uiP, unsigned int uiQ )
    {
    unsigned int i=0;
    
    //! 得到所有与z互质的数( 私钥d的集合 )
    unsigned int z = ( uiP -1 ) * ( uiQ -1 );
    pset.size = 0;
    for( i=0; i<z; i++ )
    {
    if( isPrime( i, z ) )
    {
    pset.set[ pset.size++ ] = i;
    }
    }
    
    return pset.size;
    }
    
    // 名称:MakePairKey
    // 功能:生成RSA公、私钥对
    //  参数:uiP: 素数P; uiQ: 素数Q; uiD: 私钥d
    // 返回:错误代码
    
    unsigned int MakePairkey( unsigned int uiP, unsigned int uiQ, unsigned int uiD )
    {
    bool bFlag = true;
    unsigned int i = 0, e;
    unsigned int z = ( uiP-1 ) * ( uiQ-1 );
    unsigned int d = pset.set[uiD];
    //d=uiD;
    
    if( !isPrime( z, d ) )
    return ERROR_NOEACHPRIME;
    
    for( i=2; i<z; i++ )
    {
    if( (i*d)%z == 1 )
    {
    e = i;
    bFlag = false;
    }
    }
    if( bFlag )
    return ERROR_NOPUBLICKEY;
    
    if( (d*e)%z != 1 )
    ERROR_GENERROR;
    
    pairkey.d = d;
    pairkey.e = e;
    pairkey.n = uiP * uiQ;
    return OK;
    }
    
    // 名称:GetPairKey
    // 功能:对外提供接口,获得公、私钥对
    //  参数:uiP: 素数P; uiQ: 素数Q; uiD: 私钥d
    // 返回:
    
    unsigned int GetPairKey( unsigned int &d, unsigned int &e )
    {
    d = pairkey.d;
    e = pairkey.e;
    return pairkey.n;
    }
    
    // 名称:GetPrivateKeyd
    // 功能:对外提供接口,由用户选择ID得以私钥d
    //  参数:iWhich: 用户选择私钥d的ID
    // 返回:私钥d值
    
    unsigned int GetPrivateKeyd( unsigned int iWhich )
    {
    if( pset.size >= iWhich )
    return pset.set[ iWhich ];
    else
    return 0;
    }
    
    // 名称:rsa_encrypt
    // 功能:RSA加密运算
    //  参数:n: 公钥n; e: 公钥e; mw: 加密明文; iLength: 明文长度; cw: 密文输出
    // 返回:无
    
    void rsa_encrypt( int n, int e, char *mw, int mLength, int *&cw )
    {
    int i=0, j=0;
    __int64 temInt = 0;
    
    for( i=0; i<mLength; i++ )
    {
    temInt = mw[i];
    if( e!=0 )
    {
    for( j=1; j<e; j++ )
    {
    temInt = ( temInt * mw[i] ) % n;
    }
    }
    else
    {
    temInt = 1;
    }
    
    cw[i] = (int)temInt;
    }
    }
    
    // 名称:rsa_decrypt
    // 功能:RSA解密运算
    //  参数:n: 私钥n; d: 私钥d; cw: 密文; cLength: 密文长度; mw: 明文输出
    // 返回:无
    
    void rsa_decrypt( int n, int d, int *&cw, int cLength, char *mw )
    {
    int i=0, j=-1;
    __int64 temInt = 0;
    
    for( i=0; i<cLength/4; ++i )
    {
    mw[i] = 0;
    temInt = cw[i];
    
    if( d != 0 )
    {
    for( j=1; j<d; j++ )
    {
    temInt = (__int64)( temInt * cw[i] ) % n;
    }
    }
    else
    {
    temInt = 1;
    }
    
    mw[i] = (char)temInt;
    }
    }
    void outputkey()
    {
    printf("PublicKey(e,n): (%d,%d)\n",pairkey.e,pairkey.n);
    printf("PrivateKey(d,n): (%d,%d)\n",pairkey.d,pairkey.n);
    }
    
    //main.c
    // 工程:RSA
    // 功能:RSA加、解密文件
    //  作者:jlcss|ExpNIS
    
    
    #include <stdio.h>
    #include <afxwin.h>
    #include <math.h>
    #include "rsa.h"
    
    #define DECRYPT_FILE "RSA加密密文.txt"
    #define ENCRYPT_FILE "RSA解密明文.txt"
    //! 约束文件最大2M
    #define MAX_FILE 1024*1024*2
    
    // 名称:usage
    // 功能:帮助信息
    //  参数:应用程序名称
    // 返回:提示信息
    
    void Usage( const char *appname )
    {
    printf( "\n\tusage:rsa -k 素数P 素数Q\n" );
    printf( "\tusage: rsa -e 明文文件 公钥e 公钥n\n" );
    printf( "\tusage: rsa -d 密文文件 私钥d 私钥n\n" );
    }
    
    // 名称:IsNumber
    // 功能:判断数字字符数组
    //  参数:strNumber:字符数组
    // 返回:数字字组数组返回true,否则返回false;
    
    bool IsNumber( const char *strNumber )
    {
    unsigned int i;
    
    if( !strNumber )
    return false;
    
    for ( i = 0 ; i < strlen(strNumber) ; i++ )
    {
    if ( strNumber[i] < '0' || strNumber[i] > '9' )
    return false;
    }
    
    return true;
    }
    
    // 名称:IsPrimeNumber
    // 功能:判断素数
    //  参数:num: 输入整数
    // 返回:素数返回true,否则返回false;
    
    bool IsPrimeNumber( unsigned int num )
    {
    unsigned int i;
    if( num <= 1 )
    return false;
    
    unsigned int sqr = (unsigned int)sqrt((double)num);
    for( i = 2; i <= sqr; i++ )
    {
    if( num % i == 0 )
    return false;
    }
    
    return true;
    }
    
    // 名称:FileIn
    // 功能:读取磁盘文件到内存
    //  参数:strFile:文件名称;inBuff:指向文件内容缓冲区
    // 返回:实际读取内容大小(字节)
    
    int FileIn( const char *strFile, unsigned char *&inBuff )
    {
    int iFileLen=0, iBuffLen=0;
    
    //! 打开密文文件
    CFile file( strFile, CFile::modeRead );
    iFileLen = ( int )file.GetLength();
    if( iFileLen>MAX_FILE )
    {
    printf( "文件长度不能大于 %dM,!\n", MAX_FILE/(1024*1024) );
    goto out;
    }
    iBuffLen = iFileLen;
    
    inBuff = new unsigned char[iBuffLen];
    if( !inBuff )
    goto out;
    
    ZeroMemory( inBuff, iBuffLen );
    
    file.Read( inBuff, iFileLen );
    file.Close();
    
    out:
    return iBuffLen;
    }
    
    // 名称:FileOut
    // 功能:加/解密结果输出到当前目录磁盘文件中
    //  参数:strOut指向输出字符缓冲区,输出大小len,strFile为输出文件
    // 返回:无
    
    void FileOut( const void *strOut, int len, const char *strFile )
    {
    //! 输出到文件
    CFile outfile( strFile , CFile::modeCreate | CFile::modeWrite );
    outfile.Write( strOut , len );
    outfile.Close();
    }
    
    // 名称:CheckParse
    // 功能:校验应用程序入口参数
    //  参数:argc等于main主函数argc参数,argv指向main主函数argv参数
    // 返回:若参数合法返回true,否则返回false
    //  备注:简单的入口参数校验
    
    bool CheckParse( int argc, char** argv )
    {
    bool bRes = false;
    
    if( argc != 4 && argc != 5 )
    goto out;
    
    if( argc == 4 && argv[1][1] == 'k' )
    {
    //! 生成公、私钥对
    if( !IsNumber( argv[2] ) || 
    !IsNumber( argv[3] ) ||
    atoi( argv[2] ) > MAX_PRIME ||
    atoi( argv[3] ) > MAX_PRIME )
    goto out;
    }
    else if( (argc == 5) && (argv[1][1] == 'e' || argv[1][1] == 'd') )
    {
    //! 加密、解密操作
    if( !IsNumber( argv[3] ) ||
    !IsNumber( argv[4] ) ||
    atoi( argv[3] ) > MAX_NUM ||
    atoi( argv[4] ) > MAX_NUM )
    goto out;
    }
    else
    Usage(*argv);
    bRes = true;
    
    out:
    return bRes;
    }
    
    // 名称:kOption1
    // 功能:程序k选项操作:由素数P、Q生成私钥d集合
    //  参数:uiP: 程序入口参数P; uiQ: 程序入口参数Q
    // 返回:执行正确返回生成私钥数目,否则返回0
    
    unsigned int kOption1( unsigned int uiP, unsigned int uiQ )
    {
    unsigned int uiRes = 0;
    
    if( !IsPrimeNumber( uiP ) )
    {
    printf( "P输入错误,P必须为(0, %d]素数", MAX_PRIME );
    return uiRes;
    }
    if( !IsPrimeNumber( uiQ ) )
    {
    printf( "Q输入错误,Q必须为(0, %d]素数", MAX_PRIME );
    return uiRes;
    }
    if( uiP == uiQ )
    {
    printf( "素数P与素数Q相同,很容易根据公钥n开平方得出素数P和Q,这种加密不安全,请更换素数!\n" );
    return uiRes;
    }
    printf( "正在生成私钥d集合......\n" );
    uiRes = MakePrivatedKeyd( uiP, uiQ );
    
    return uiRes;
    }
    
    //! 程序主函数
    int main( int argc, char **argv )
    {
    unsigned int p , q , d , n , e;//two prime p & q, public key(n, e) , private key(n , d)
    CheckParse(argc,  argv );
    
    d=4828; //uid
    if(argc == 4)
    {
    p = atoi( argv[2] );
    q = atoi( argv[3] );
    MakePrivatedKeyd(p, q);
    MakePairkey(p, q, d );
    outputkey();
    }
    else if(argc == 5)
    {
    char FileName[20];
    strcpy(FileName, argv[2]);
    int len;
    if(argv[1][1] == 'e' )
    {
    unsigned char *inBuffer=(unsigned char *)malloc(MAX_FILE); //输入缓冲区
    int *cw=(int *)malloc(MAX_FILE);
    len = FileIn(FileName , inBuffer);
    e = atoi(argv[3]);
    n = atoi(argv[4]);
    rsa_encrypt( n, e, (char *)inBuffer, len, cw );
    FileOut( cw, 4*len, DECRYPT_FILE );
    }
    else if(argv[1][1] == 'd')
    {
    char *Buffer=(char *)malloc(MAX_FILE); //输入缓冲区
    int *cw=(int *)malloc(MAX_FILE);
    len = FileIn(FileName, (unsigned char *&)cw);
    d = atoi(argv[3]);
    n = atoi(argv[4]);
    rsa_decrypt( n, d, cw, len, Buffer );
    FileOut( Buffer, len/4, ENCRYPT_FILE );
    }
    }
    
    return 0;
    }
    

    二 运行

    展开全文
  • RSA算法C语言实现.zip

    2019-09-25 17:02:32
    C语言实现的RSA算法源码 Visual Studio工程 支持公钥加解密 私钥加解密
  • RSA算法C语言程序

    热门讨论 2010-05-18 15:40:29
    RSA算法C语言实现程序,绝对好用,内含运行结果
  • RSA算法C语言代码.pdf

    2020-11-12 01:14:30
    #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include <time.h> char s[100]*c; int n,e,d,i,C,j,k=0,len; int str[100],b[30]; unsigned gcd(unsigned a, unsigned b ) { if(a
  • RSA算法C语言代码.docx

    2020-08-07 07:26:36
    #in elude <stdlib.h> #in elude <stdio.h> #in elude <stri ng.h> #in elude <math.h> #in elude <time.h> char s[100]*c; int n ,e,d,i,C,j,k=O,le n; int str[100],b[30]; un sig ned gcd(un sig ned a, un sig n
  • #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include <time.h> char s[100]*c; int n,e,d,i,C,j,k=0,len; int str[100],b[30]; unsigned gcd(unsigned a, unsigned b ) { if(a%
  • 非对称加密RSA算法c语言实现

    千次阅读 2019-12-01 16:04:05
    相对于“对称加密算法”这种方法也叫做“非对称加密算法”。与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密 (privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对...

    1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。相对于“对称加密算法”这种方法也叫做“非对称加密算法”。与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密 (privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法

    非对称密钥(public-key cryptography),又称为公开密钥加密,服务端会生成一对密钥,一个私钥保存在服务端,仅自己知道,另一个是公钥,公钥可以自由发布供任何人使用。客户端的明文通过公钥加密后的密文需要用私钥解密。非对称密钥在加密和解密的过程的使用的密钥是不同的密钥,加密和解密是不对称的,所以称之为非对称加密。与对称密钥加密相比,非对称加密无需在客户端和服务端之间共享密钥,只要私钥不发给任何用户,即使公钥在网上被截获,也无法被解密,仅有被窃取的公钥是没有任何用处的。我们常见的数字证书、加密狗即是采用非对称加密来完成安全验证的常见的非对称加密算法有RSA、Elgamal、背包算法、Rabin、HD,ECC(椭圆曲线加密算法),非对称加解密的过程:

    服务端生成配对的公钥和私钥

    私钥保存在服务端,公钥发送给客户端

    客户端使用公钥加密明文传输给服务端

    服务端使用私钥解密密文得到明文

    优点:安全性更高,公钥是公开的,秘钥是自己保存的,不需要将私钥给别人。

    缺点:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。

    非对称加密的流程图如下所示:途中密钥M和密钥N一个为私钥,一个为公钥

     

    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    #ifdef __cplusplus
        extern "C" {
    #endif
    
    /* Length of digit in bits */
    #define NN_DIGIT_BITS 32
    #define NN_HALF_DIGIT_BITS 16
    /* Length of digit in bytes */
    #define NN_DIGIT_LEN (NN_DIGIT_BITS / 8)
    /* Maximum length in digits */
    #define MAX_NN_DIGITS   ((MAX_RSA_MODULUS_LEN + NN_DIGIT_LEN - 1) / NN_DIGIT_LEN + 1)
    /* Maximum digits */
    #define MAX_NN_DIGIT 0xffffffff
    #define MAX_NN_HALF_DIGIT 0xffff
    /* Macros.*/
    #define LOW_HALF(x) ((x) & MAX_NN_HALF_DIGIT)
    #define HIGH_HALF(x) (((x) >> NN_HALF_DIGIT_BITS) & MAX_NN_HALF_DIGIT)
    #define TO_HIGH_HALF(x) (((NN_DIGIT)(x)) << NN_HALF_DIGIT_BITS)
    #define DIGIT_MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 1)) & 1)
    #define DIGIT_2MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 2)) & 3)
    
    #define NN_ASSIGN_DIGIT(a, b, digits) {NN_AssignZero (a, digits); a[0] = b;}
    #define NN_EQUAL(a, b, digits) (! NN_Cmp (a, b, digits))
    #define NN_EVEN(a, digits) (((digits) == 0) || ! (a[0] & 1))
    
    /* RSA key lengths.*/
    #define MIN_RSA_MODULUS_BITS 64 //wyh raw 508
    #define MAX_RSA_MODULUS_BITS 2048 // WYH RAW 1024
    #define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8)
    #define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2)
    #define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8)
    
    /* Maximum lengths of encoded and encrypted content, as a function of
       content length len. Also, inverse functions.*/
    #define ENCODED_CONTENT_LEN(len) (4*(len)/3 + 3)
    #define ENCRYPTED_CONTENT_LEN(len) ENCODED_CONTENT_LEN ((len)+8)
    #define DECODED_CONTENT_LEN(len) (3*(len)/4 + 1)
    #define DECRYPTED_CONTENT_LEN(len) (DECODED_CONTENT_LEN (len) - 1)
    
    /* Maximum length of Diffie-Hellman parameters.*/
    #define DH_PRIME_LEN(bits) (((bits) + 7) / 8)
    
    /* Error codes.*/
    #define RE_CONTENT_ENCODING 0x0400
    #define RE_DATA 0x0401
    #define RE_DIGEST_ALGORITHM 0x0402
    #define RE_ENCODING 0x0403
    #define RE_KEY 0x0404
    #define RE_KEY_ENCODING 0x0405
    #define RE_LEN 0x0406
    #define RE_MODULUS_LEN 0x0407
    #define RE_NEED_RANDOM 0x0408
    #define RE_PRIVATE_KEY 0x0409
    #define RE_PUBLIC_KEY 0x040a
    #define RE_SIGNATURE 0x040b
    #define RE_SIGNATURE_ENCODING 0x040c
    #define RE_ENCRYPTION_ALGORITHM 0x040d
    
    /* Random structure.*/
    typedef struct {
        unsigned int bytesNeeded;
        unsigned char state[16];
        unsigned int outputAvailable;
        unsigned char output[16];
    } R_RANDOM_STRUCT;
    
    /* RSA public and private key.*/
    typedef struct {
        unsigned int bits;                           /* length in bits of modulus */
        unsigned char modulus[MAX_RSA_MODULUS_LEN];                    /* modulus :N */
        unsigned char exponent[MAX_RSA_MODULUS_LEN];           /* public exponent :E */
    } R_RSA_PUBLIC_KEY;
    
    typedef struct {
        unsigned int bits;                           /* length in bits of modulus */
        unsigned char modulus[MAX_RSA_MODULUS_LEN];                    /* modulus :N*/
        unsigned char publicExponent[MAX_RSA_MODULUS_LEN];     /* public exponent :E*/
        unsigned char exponent[MAX_RSA_MODULUS_LEN];          /* private exponent :D*/
        unsigned char prime[2][MAX_RSA_PRIME_LEN];               /* prime factors :P,Q*/
        unsigned char primeExponent[2][MAX_RSA_PRIME_LEN];   /* exponents for CRT :dP,dQ*/
        unsigned char coefficient[MAX_RSA_PRIME_LEN];          /* CRT coefficient :qInv*/
    } R_RSA_PRIVATE_KEY;
    
    /* RSA prototype key.*/
    typedef struct {
        unsigned int bits;    /* length in bits of modulus */
        int useFermat4;       /* public exponent (1 = F4, 0 = 3) */
    } R_RSA_PROTO_KEY;
    
    
    /* PROTOTYPES should be set to one if and only if the compiler supports
        function argument prototyping.
        The following makes PROTOTYPES default to 1 if it has not already been
        defined as 0 with C compiler flags.
    */
    #ifndef PROTOTYPES
    #define PROTOTYPES 1
    #endif
    
    /* POINTER defines a generic pointer type */
    typedef unsigned char *POINTER;
    
    /* UINT2 defines a two byte word */
    typedef unsigned short int UINT2;
    
    /* UINT4 defines a four byte word */
    typedef unsigned long int UINT4;
    
    /* Type definitions.*/
    typedef UINT4 NN_DIGIT;
    typedef UINT2 NN_HALF_DIGIT;
    
    #ifndef NULL_PTR
    #define NULL_PTR ((POINTER)0)
    #endif
    
    #ifndef UNUSED_ARG
    #define UNUSED_ARG(x) x = *(&x);
    #endif
    
    /* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
        If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
        returns an empty list.
    */
    #if PROTOTYPES
    #define PROTO_LIST(list) list
    #else
    #define PROTO_LIST(list) ()
    #endif
    
    int RSAPublicBlock PROTO_LIST((unsigned char *output, unsigned int *outputLen,
            unsigned char *input, unsigned int inputLen,
            R_RSA_PUBLIC_KEY *));
    
    int RSAPrivateBlock PROTO_LIST((unsigned char *output, unsigned int *outputLen,
            unsigned char *input, unsigned int inputLen,
            R_RSA_PRIVATE_KEY *));
    
    
    
    
    #define R_memset memset
    #define R_memcpy memcpy
    #define R_memcmp memcmp
    
    static NN_DIGIT NN_AddDigitMult
      (NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
    static NN_DIGIT NN_SubDigitMult
      (NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
    
    static unsigned int NN_DigitBits  (NN_DIGIT);
    
    /* Decodes character string b into a, where character string is ordered
       from most to least significant.
       Lengths: a[digits], b[len].
       Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
       significant bytes are truncated.)
     */
    void NN_Decode (NN_DIGIT *a,
                    unsigned int digits,
                    unsigned char *b,
                    unsigned int len)
    
    {
        NN_DIGIT t;
        int j;
        unsigned int i, u;
    
        for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
            t = 0;
            for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
                t |= ((NN_DIGIT)b[j]) << u;
            a[i] = t;
        }
    
        for (; i < digits; i++)
            a[i] = 0;
    }
    
    /* Encodes b into character string a, where character string is ordered
       from most to least significant.
       Lengths: a[len], b[digits].
       Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
       digits are truncated.)
     */
    void NN_Encode(unsigned char *a,
                   unsigned int len,
                   NN_DIGIT *b,
                   unsigned int digits)
    
    {
        NN_DIGIT t;
        int j;
        unsigned int i, u;
    
        for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
            t = b[i];
            for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
                a[j] = (unsigned char)(t >> u);
        }
    
        for (; j >= 0; j--)
            a[j] = 0;
    }
    
    /* Assigns a = b.
       Lengths: a[digits], b[digits].
     */
    void NN_Assign(NN_DIGIT *a,
                    NN_DIGIT *b,
                    unsigned int digits)
    {
        unsigned int i;
    
        for (i = 0; i < digits; i++)
            a[i] = b[i];
    }
    
    /* Assigns a = 0.
       Lengths: a[digits].
     */
    void NN_AssignZero (NN_DIGIT *a,
                        unsigned int digits)
    {
        unsigned int i;
    
        for (i = 0; i < digits; i++)
            a[i] = 0;
    }
    
    /* Assigns a = 2^b.
       Lengths: a[digits].
       Requires b < digits * NN_DIGIT_BITS.
     */
    void NN_Assign2Exp (NN_DIGIT *a,
                        unsigned int b,
                        unsigned int digits)
    {
        NN_AssignZero (a, digits);
    
        if (b >= digits * NN_DIGIT_BITS)
            return;
    
        a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
    }
    
    /* Computes a = b + c. Returns carry.
       Lengths: a[digits], b[digits], c[digits].
     */
    NN_DIGIT NN_Add (NN_DIGIT *a,
                    NN_DIGIT *b,
                    NN_DIGIT *c,
                    unsigned int digits)
    {
        NN_DIGIT ai, carry;
        unsigned int i;
    
        carry = 0;
    
        for (i = 0; i < digits; i++) {
            if ((ai = b[i] + carry) < carry)
                ai = c[i];
            else if ((ai += c[i]) < c[i])
                carry = 1;
            else
                carry = 0;
            a[i] = ai;
        }
    
        return (carry);
    }
    
    /* Computes a = b - c. Returns borrow.
       Lengths: a[digits], b[digits], c[digits].
     */
    NN_DIGIT NN_Sub (NN_DIGIT *a,
                    NN_DIGIT *b,
                    NN_DIGIT * c,
                    unsigned int digits)
    {
        NN_DIGIT ai, borrow;
        unsigned int i;
    
        borrow = 0;
    
        for (i = 0; i < digits; i++) {
            if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
                ai = MAX_NN_DIGIT - c[i];
            else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i]))
                borrow = 1;
            else
                borrow = 0;
            a[i] = ai;
        }
    
        return (borrow);
    }
    
    
    /* Returns sign of a - b.
       Lengths: a[digits], b[digits].
     */
    int NN_Cmp (NN_DIGIT *a,
                NN_DIGIT *b,
                unsigned int digits)
    
    {
        int i;
    
        for (i = digits - 1; i >= 0; i--) {
            if (a[i] > b[i])
                return (1);
            if (a[i] < b[i])
                return (-1);
        }
    
        return (0);
    }
    
    /* Returns nonzero iff a is zero.
       Lengths: a[digits].
     */
    int NN_Zero (NN_DIGIT *a,
                unsigned int digits)
    {
        unsigned int i;
    
        for (i = 0; i < digits; i++)
            if (a[i])
                return (0);
    
        return (1);
    }
    
    /* Returns the significant length of a in digits.
       Lengths: a[digits].
     */
    unsigned int NN_Digits (NN_DIGIT *a,
                            unsigned int digits)
    
    {
        int i;
    
        for (i = digits - 1; i >= 0; i--)
            if (a[i])
                break;
    
        return (i + 1);
    }
    /* Returns the significant length of a in bits.
       Lengths: a[digits].
     */
    unsigned int NN_Bits (NN_DIGIT *a,
                            unsigned int digits)
    {
        if ((digits = NN_Digits (a, digits)) == 0)
            return (0);
    
        return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
    }
    
    
    
    /* Computes a = b * c.
       Lengths: a[2*digits], b[digits], c[digits].
       Assumes digits < MAX_NN_DIGITS.
     */
    void NN_Mult (NN_DIGIT *a,
                    NN_DIGIT *b,
                    NN_DIGIT *c,
                    unsigned int digits)
    {
        NN_DIGIT t[2*MAX_NN_DIGITS];
        unsigned int bDigits, cDigits, i;
    
        NN_AssignZero (t, 2 * digits);
    
        bDigits = NN_Digits (b, digits);
        cDigits = NN_Digits (c, digits);
    
        for (i = 0; i < bDigits; i++)
        t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
    
        NN_Assign (a, t, 2 * digits);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)t, 0, sizeof (t));
    }
    
    /* Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
       Lengths: a[digits], b[digits].
       Requires c < NN_DIGIT_BITS.
     */
    NN_DIGIT NN_LShift (NN_DIGIT *a,
                        NN_DIGIT *b,
                        unsigned int c,
                        unsigned int digits)
    {
        NN_DIGIT bi, carry;
        unsigned int i, t;
    
        if (c >= NN_DIGIT_BITS)
            return (0);
    
        t = NN_DIGIT_BITS - c;
    
        carry = 0;
    
        for (i = 0; i < digits; i++) {
            bi = b[i];
            a[i] = (bi << c) | carry;
            carry = c ? (bi >> t) : 0;
        }
    
        return (carry);
    }
    
    /* Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
       Lengths: a[digits], b[digits].
       Requires: c < NN_DIGIT_BITS.
     */
    NN_DIGIT NN_RShift (NN_DIGIT *a,
                        NN_DIGIT *b,
                        unsigned int c,
                        unsigned int digits)
    
    {
        NN_DIGIT bi, carry;
        int i;
        unsigned int t;
    
        if (c >= NN_DIGIT_BITS)
            return (0);
    
        t = NN_DIGIT_BITS - c;
    
        carry = 0;
    
        for (i = digits - 1; i >= 0; i--) {
            bi = b[i];
            a[i] = (bi >> c) | carry;
            carry = c ? (bi << t) : 0;
        }
    
        return (carry);
    }
    
    
    /* Computes a = b * c, where b and c are digits.
       Lengths: a[2].
     */
    void NN_DigitMult (NN_DIGIT a[2],NN_DIGIT b, NN_DIGIT c)
    {
        NN_DIGIT t, u;
        NN_HALF_DIGIT bHigh, bLow, cHigh, cLow;
    
        bHigh = (NN_HALF_DIGIT)HIGH_HALF (b);
        bLow = (NN_HALF_DIGIT)LOW_HALF (b);
        cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
        cLow = (NN_HALF_DIGIT)LOW_HALF (c);
    
        a[0] = (NN_DIGIT)bLow * (NN_DIGIT)cLow;
        t = (NN_DIGIT)bLow * (NN_DIGIT)cHigh;
        u = (NN_DIGIT)bHigh * (NN_DIGIT)cLow;
        a[1] = (NN_DIGIT)bHigh * (NN_DIGIT)cHigh;
    
        if ((t += u) < u)
            a[1] += TO_HIGH_HALF (1);
        u = TO_HIGH_HALF (t);
    
        if ((a[0] += u) < u)
            a[1]++;
        a[1] += HIGH_HALF (t);
    }
    
    /* Sets a = b / c, where a and c are digits.
       Lengths: b[2].
       Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be
       normalized.
     */
    void NN_DigitDiv (NN_DIGIT *a,NN_DIGIT b[2], NN_DIGIT c)
    {
        NN_DIGIT t[2], u, v;
        NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
    
        cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
        cLow = (NN_HALF_DIGIT)LOW_HALF (c);
    
        t[0] = b[0];
        t[1] = b[1];
    
        /* Underestimate high half of quotient and subtract.
        */
        if (cHigh == MAX_NN_HALF_DIGIT)
            aHigh = (NN_HALF_DIGIT)HIGH_HALF (t[1]);
        else
            aHigh = (NN_HALF_DIGIT)(t[1] / (cHigh + 1));
    
        u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow;
        v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh;
        if ((t[0] -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u)))
            t[1]--;
        t[1] -= HIGH_HALF (u);
        t[1] -= v;
    
        /* Correct estimate.
        */
        while ((t[1] > cHigh) ||
        ((t[1] == cHigh) && (t[0] >= TO_HIGH_HALF (cLow)))) {
            if ((t[0] -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow))
                t[1]--;
    
            t[1] -= cHigh;
            aHigh++;
        }
    
        /* Underestimate low half of quotient and subtract.
        */
        if (cHigh == MAX_NN_HALF_DIGIT)
            aLow = (NN_HALF_DIGIT)LOW_HALF (t[1]);
        else
            aLow =
            (NN_HALF_DIGIT)((TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) / (cHigh + 1));
    
        u = (NN_DIGIT)aLow * (NN_DIGIT)cLow;
        v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh;
        if ((t[0] -= u) > (MAX_NN_DIGIT - u))
            t[1]--;
        if ((t[0] -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v)))
            t[1]--;
    
        t[1] -= HIGH_HALF (v);
    
        /* Correct estimate.
        */
        while ((t[1] > 0) || ((t[1] == 0) && t[0] >= c)) {
            if ((t[0] -= c) > (MAX_NN_DIGIT - c))
                t[1]--;
            aLow++;
        }
    
        *a = TO_HIGH_HALF (aHigh) + aLow;
    }
    
    /* Computes a = c div d and b = c mod d.
       Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
       Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
               dDigits < MAX_NN_DIGITS.
     */
    void NN_Div (NN_DIGIT *a,
                    NN_DIGIT *b,
                    NN_DIGIT *c,
                    unsigned int cDigits,
                    NN_DIGIT *d,
                    unsigned int dDigits)
    
    {
        NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
        int i;
        unsigned int ddDigits, shift;
    
        ddDigits = NN_Digits (d, dDigits);
        if (ddDigits == 0)
            return;
    
        /* Normalize operands.
        */
        shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
        NN_AssignZero (cc, ddDigits);
        cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
        NN_LShift (dd, d, shift, ddDigits);
        t = dd[ddDigits-1];
    
        NN_AssignZero (a, cDigits);
    
        for (i = cDigits-ddDigits; i >= 0; i--) {
            /* Underestimate quotient digit and subtract.
            */
            if (t == MAX_NN_DIGIT)
                ai = cc[i+ddDigits];
            else
                NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
            cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
    
            /* Correct estimate.
            */
            while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) {
                ai++;
                cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
            }
    
            a[i] = ai;
        }
    
        /* Restore result.
        */
        NN_AssignZero (b, dDigits);
        NN_RShift (b, cc, shift, ddDigits);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)cc, 0, sizeof (cc));
        R_memset ((POINTER)dd, 0, sizeof (dd));
    }
    
    /* Computes a = b mod c.
       Lengths: a[cDigits], b[bDigits], c[cDigits].
       Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
     */
    void NN_Mod (NN_DIGIT *a,
                    NN_DIGIT *b,
                    unsigned int bDigits,
                    NN_DIGIT *c,
                    unsigned int cDigits)
    {
        NN_DIGIT t[2 * MAX_NN_DIGITS];
    
        NN_Div (t, a, b, bDigits, c, cDigits);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)t, 0, sizeof (t));
    }
    
    /* Computes a = b * c mod d.
       Lengths: a[digits], b[digits], c[digits], d[digits].
       Assumes d > 0, digits < MAX_NN_DIGITS.
     */
    void NN_ModMult (NN_DIGIT *a,
                    NN_DIGIT *b,
                    NN_DIGIT *c,
                    NN_DIGIT *d,
                    unsigned int digits)
    
    {
        NN_DIGIT t[2*MAX_NN_DIGITS];
    
        NN_Mult (t, b, c, digits);
        NN_Mod (a, t, 2 * digits, d, digits);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)t, 0, sizeof (t));
    }
    
    /* Computes a = b^c mod d.
       Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
       Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
     */
    
    /* PGP 2.5's mpilib contains a faster modular exponentiation routine, mp_modexp.
       If USEMPILIB is defined, NN_ModExp is replaced in the PGP 2.5 sources with a
       stub call to mp_modexp.  If USEMPILIB is not defined, we'll get a pure (albeit
       slower) RSAREF implementation.
       The RSAREF 2.0 license, clause 1(c), permits "...modify[ing] the Program in any
       manner for porting or performance improvement purposes..." */
    
    #ifndef USEMPILIB
    void NN_ModExp (NN_DIGIT *a,
                    NN_DIGIT *b,
                    NN_DIGIT *c,
                    unsigned int cDigits,
                    NN_DIGIT *d,
                    unsigned int dDigits)
    
    {
        NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
        int i;
        unsigned int ciBits, j, s;
    
        /* Store b, b^2 mod d, and b^3 mod d.
        */
        NN_Assign (bPower[0], b, dDigits);
        NN_ModMult (bPower[1], bPower[0], b, d, dDigits);
        NN_ModMult (bPower[2], bPower[1], b, d, dDigits);
    
        NN_ASSIGN_DIGIT (t, 1, dDigits);
    
        cDigits = NN_Digits (c, cDigits);
        for (i = cDigits - 1; i >= 0; i--) {
            ci = c[i];
            ciBits = NN_DIGIT_BITS;
    
            /* Scan past leading zero bits of most significant digit.
            */
            if (i == (int)(cDigits - 1)) {
                while (! DIGIT_2MSB (ci)) {
                    ci <<= 2;
                    ciBits -= 2;
                }
            }
    
            for (j = 0; j < ciBits; j += 2, ci <<= 2) {
                /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci.
                */
                NN_ModMult (t, t, t, d, dDigits);
                NN_ModMult (t, t, t, d, dDigits);
                if ((s = DIGIT_2MSB (ci)) != 0)
                    NN_ModMult (t, t, bPower[s-1], d, dDigits);
            }
        }
    
        NN_Assign (a, t, dDigits);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)bPower, 0, sizeof (bPower));
        R_memset ((POINTER)t, 0, sizeof (t));
    }
    #endif
    
    /* Compute a = 1/b mod c, assuming inverse exists.
       Lengths: a[digits], b[digits], c[digits].
       Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
     */
    void NN_ModInv (NN_DIGIT *a,
                    NN_DIGIT *b,
                    NN_DIGIT *c,
                    unsigned int digits)
    {
        NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS],
                u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS],
                v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS];
        int u1Sign;
    
        /* Apply extended Euclidean algorithm, modified to avoid negative
        numbers.
        */
        NN_ASSIGN_DIGIT (u1, 1, digits);
        NN_AssignZero (v1, digits);
        NN_Assign (u3, b, digits);
        NN_Assign (v3, c, digits);
        u1Sign = 1;
    
        while (! NN_Zero (v3, digits)) {
            NN_Div (q, t3, u3, digits, v3, digits);
            NN_Mult (w, q, v1, digits);
            NN_Add (t1, u1, w, digits);
            NN_Assign (u1, v1, digits);
            NN_Assign (v1, t1, digits);
            NN_Assign (u3, v3, digits);
            NN_Assign (v3, t3, digits);
            u1Sign = -u1Sign;
        }
    
        /* Negate result if sign is negative.
        */
        if (u1Sign < 0)
            NN_Sub (a, c, u1, digits);
        else
            NN_Assign (a, u1, digits);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)q, 0, sizeof (q));
        R_memset ((POINTER)t1, 0, sizeof (t1));
        R_memset ((POINTER)t3, 0, sizeof (t3));
        R_memset ((POINTER)u1, 0, sizeof (u1));
        R_memset ((POINTER)u3, 0, sizeof (u3));
        R_memset ((POINTER)v1, 0, sizeof (v1));
        R_memset ((POINTER)v3, 0, sizeof (v3));
        R_memset ((POINTER)w, 0, sizeof (w));
    }
    
    /* Computes a = gcd(b, c).
       Lengths: a[digits], b[digits], c[digits].
       Assumes b > c, digits < MAX_NN_DIGITS.
     */
    void NN_Gcd (NN_DIGIT *a,
                NN_DIGIT *b,
                NN_DIGIT *c,
                unsigned int digits)
    
    {
        NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
    
        NN_Assign (u, b, digits);
        NN_Assign (v, c, digits);
    
        while (! NN_Zero (v, digits)) {
            NN_Mod (t, u, digits, v, digits);
            NN_Assign (u, v, digits);
            NN_Assign (v, t, digits);
        }
    
        NN_Assign (a, u, digits);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)t, 0, sizeof (t));
        R_memset ((POINTER)u, 0, sizeof (u));
        R_memset ((POINTER)v, 0, sizeof (v));
    }
    
    /* Computes a = b + c*d, where c is a digit. Returns carry.
       Lengths: a[digits], b[digits], d[digits].
     */
    static NN_DIGIT NN_AddDigitMult (NN_DIGIT *a,
                                     NN_DIGIT *b,
                                     NN_DIGIT c,
                                     NN_DIGIT *d,
                                     unsigned int digits)
    
    {
        NN_DIGIT carry, t[2];
        unsigned int i;
    
        if (c == 0)
            return (0);
    
        carry = 0;
        for (i = 0; i < digits; i++) {
            NN_DigitMult (t, c, d[i]);
            if ((a[i] = b[i] + carry) < carry)
                carry = 1;
            else
                carry = 0;
    
            if ((a[i] += t[0]) < t[0])
                carry++;
            carry += t[1];
        }
    
        return (carry);
    }
    
    /* Computes a = b - c*d, where c is a digit. Returns borrow.
       Lengths: a[digits], b[digits], d[digits].
     */
    static NN_DIGIT NN_SubDigitMult (NN_DIGIT *a,
                                     NN_DIGIT *b,
                                     NN_DIGIT c,
                                     NN_DIGIT *d,
                                     unsigned int digits)
    {
        NN_DIGIT borrow, t[2];
        unsigned int i;
    
        if (c == 0)
            return (0);
    
        borrow = 0;
        for (i = 0; i < digits; i++) {
            NN_DigitMult (t, c, d[i]);
            if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
                borrow = 1;
            else
                borrow = 0;
    
            if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
                borrow++;
    
            borrow += t[1];
        }
    
        return (borrow);
    }
    
    /* Returns the significant length of a in bits, where a is a digit.
     */
    static unsigned int NN_DigitBits (NN_DIGIT a)
    {
        unsigned int i;
    
        for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)
            if (a == 0)
                break;
        return (i);
    }
    
    
    /**
    RSA public-key PublicBlock and RSAPrivateBlock.
    **/
    
    int RSAPublicBlock(unsigned char *, unsigned int *,
            unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *);
    int RSAPrivateBlock(unsigned char *, unsigned int *,
            unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *);
    
    /* RSA public-key encryption, according to PKCS #1.
     */
    int RSAPublicEncrypt(unsigned char *output,                                      /* output block */
            unsigned int *outputLen,                          /* length of output block */
            unsigned char *input,                                        /* input block */
            unsigned int inputLen,                             /* length of input block */
            R_RSA_PUBLIC_KEY *publicKey)                         /* RSA public key */
    {
        int status;
        unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN];
        unsigned int i, modulusLen;
    
        modulusLen = (publicKey->bits + 7) / 8;
        if (inputLen + 11 > modulusLen)
            return (RE_LEN);
    
        pkcsBlock[0] = 0;
        /* block type 2 */
        pkcsBlock[1] = 2;
    
        for (i = 2; i < modulusLen - inputLen - 1; i++) {
            /* Find nonzero random byte.
            */
            //do {
            //R_GenerateBytes (&byte, 1, randomStruct);
            //} while (byte == 0);
            //pkcsBlock[i] = byte;
        }
        /* separator */
        //pkcsBlock[i++] = 0;
        R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
        status = RSAPublicBlock(output, outputLen, pkcsBlock, modulusLen, publicKey);
    
        /* Zeroize sensitive information.
        */
        byte = 0;
        R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
    
        return (status);
    }
    /* wyhadd this function for raw rsa encrypt
    output: buf for result, buffer must be >= (publicKey->bits + 7) / 8.
    outputlen: result len
    input: data to be encrypted
    inputlen: input data len
    publicKey: n,e,bits len
    randomStruct: not used
    notice:
    data endian: input[0] is the biggest, input[len-1] is the lest
    output: the first data is output[(publicKey->bits + 7) / 8-1]
    */
    int wyhRSAPublicEncrypt (unsigned char *output,                                      /* output block */
                        unsigned int *outputLen,                          /* length of output block */
                        unsigned char *input,                                        /* input block */
                        unsigned int inputLen,                             /* length of input block */
                        R_RSA_PUBLIC_KEY *publicKey,                              /* RSA public key */
                        R_RANDOM_STRUCT *randomStruct)                          /* random structure */
    {
        int status;
        unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN];
        unsigned int i, modulusLen;
    
        modulusLen = (publicKey->bits + 7) / 8;
        if (inputLen > modulusLen)
            return (RE_LEN);
    
        status = RSAPublicBlock(output, outputLen, input, inputLen, publicKey);
    
        return (status);
    }
    
    
    
    /* RSA public-key decryption, according to PKCS #1.
     */
    int RSAPublicDecrypt (unsigned char *output,                                      /* output block */
                        unsigned int *outputLen,                          /* length of output block */
                        unsigned char *input,                                        /* input block */
                        unsigned int inputLen,                             /* length of input block */
                        R_RSA_PUBLIC_KEY *publicKey)                              /* RSA public key */
    {
        int status;
        unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
        unsigned int i, modulusLen, pkcsBlockLen;
    
        modulusLen = (publicKey->bits + 7) / 8;
        if (inputLen > modulusLen)
            return (RE_LEN);
    
        if (status = RSAPublicBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey))
            return (status);
    
        if (pkcsBlockLen != modulusLen)
            return (RE_LEN);
    
        /* Require block type 1.
        */
        if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1))
            return (RE_DATA);
    
        for (i = 2; i < modulusLen-1; i++)
            if (pkcsBlock[i] != 0xff)
                break;
    
        /* separator */
        if (pkcsBlock[i++] != 0)
            return (RE_DATA);
    
        *outputLen = modulusLen - i;
    
        if (*outputLen + 11 > modulusLen)
            return (RE_DATA);
    
        R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
    
        return (0);
    }
    
    
    
    /* RSA private-key encryption, according to PKCS #1.
     */
    int RSAPrivateEncrypt (unsigned char *output,                                      /* output block */
                            unsigned int *outputLen,                          /* length of output block */
                            unsigned char *input,                                        /* input block */
                            unsigned int inputLen,                             /* length of input block */
                            R_RSA_PRIVATE_KEY *privateKey)                           /* RSA private key */
    {
        int status;
        unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
        unsigned int i, modulusLen;
    
        modulusLen = (privateKey->bits + 7) / 8;
    #if 1 //PCKS1填充
        if (inputLen + 11 > modulusLen)
            return (RE_LEN);
    
        pkcsBlock[0] = 0;
        /* block type 1 */
        pkcsBlock[1] = 1;
    
        for (i = 2; i < modulusLen - inputLen - 1; i++)
            pkcsBlock[i] = 0xff;
    
        /* separator */
        pkcsBlock[i++] = 0;
    
        R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
    #endif
        //   R_memcpy ((POINTER)&pkcsBlock[0], (POINTER)input, inputLen);
    
    
        status = RSAPrivateBlock(output, outputLen, pkcsBlock, modulusLen, privateKey);
    
        /* Zeroize potentially sensitive information.
        */
        R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
    
        return (status);
    }
    
    /* RSA private-key decryption, according to PKCS #1.
     */
    int RSAPrivateDecrypt (unsigned char *output,                                      /* output block */
                            unsigned int *outputLen,                          /* length of output block */
                            unsigned char *input,                                        /* input block */
                            unsigned int inputLen,                             /* length of input block */
                            R_RSA_PRIVATE_KEY *privateKey)                           /* RSA private key */
    {
        int status;
        unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
        unsigned int i, modulusLen, pkcsBlockLen;
    
        modulusLen = (privateKey->bits + 7) / 8;
        if (inputLen > modulusLen)
            return (RE_LEN);
    
        if (status = RSAPrivateBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey))
            return (status);
    
        if (pkcsBlockLen != modulusLen)
            return (RE_LEN);
    
        /* Require block type 2.
        */
        if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 2))
            return (RE_DATA);
    
        for (i = 2; i < modulusLen-1; i++)
            /* separator */
            if (pkcsBlock[i] == 0)
                break;
    
        i++;
        if (i >= modulusLen)
            return (RE_DATA);
    
        *outputLen = modulusLen - i;
    
        if (*outputLen + 11 > modulusLen)
            return (RE_DATA);
    
        R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
        /* Zeroize sensitive information.
        */
        R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
        return (0);
    }
    
    /* Raw RSA public-key operation. Output has same length as modulus.
       Assumes inputLen < length of modulus.
       Requires input < modulus.
     */
    int RSAPublicBlock (unsigned char *output,                                      /* output block */
                        unsigned int *outputLen,                          /* length of output block */
                        unsigned char *input,                                        /* input block */
                        unsigned int inputLen,                             /* length of input block */
                        R_RSA_PUBLIC_KEY *publicKey)                              /* RSA public key */
    {
        NN_DIGIT c[MAX_NN_DIGITS], e[MAX_NN_DIGITS], m[MAX_NN_DIGITS],
                n[MAX_NN_DIGITS];
        unsigned int eDigits, nDigits;
    
        NN_Decode (m, MAX_NN_DIGITS, input, inputLen);
        NN_Decode (n, MAX_NN_DIGITS, publicKey->modulus, MAX_RSA_MODULUS_LEN);
        NN_Decode (e, MAX_NN_DIGITS, publicKey->exponent, MAX_RSA_MODULUS_LEN);
        nDigits = NN_Digits (n, MAX_NN_DIGITS);
        eDigits = NN_Digits (e, MAX_NN_DIGITS);
    
        if (NN_Cmp (m, n, nDigits) >= 0)
            return (RE_DATA);
    
        /* Compute c = m^e mod n.
        */
        NN_ModExp (c, m, e, eDigits, n, nDigits);
    
        *outputLen = (publicKey->bits + 7) / 8;
        NN_Encode (output, *outputLen, c, nDigits);
    
        /* Zeroize sensitive information.
        */
        R_memset ((POINTER)c, 0, sizeof (c));
        R_memset ((POINTER)m, 0, sizeof (m));
    
        return (0);
    }
    
    /* Raw RSA private-key operation. Output has same length as modulus.
       Assumes inputLen < length of modulus.
       Requires input < modulus.
     */
    int RSAPrivateBlock (unsigned char *output,                                      /* output block */
            unsigned int *outputLen,                          /* length of output block */
            unsigned char *input,                                        /* input block */
            unsigned int inputLen,                             /* length of input block */
            R_RSA_PRIVATE_KEY *privateKey)                           /* RSA private key */
    {
        NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS],
                dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS],
                mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS],
                qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS];
        unsigned int cDigits, nDigits, pDigits;
    
        NN_Decode (c, MAX_NN_DIGITS, input, inputLen);
        NN_Decode (n, MAX_NN_DIGITS, privateKey->modulus, MAX_RSA_MODULUS_LEN);
        NN_Decode (p, MAX_NN_DIGITS, privateKey->prime[0], MAX_RSA_PRIME_LEN);
        NN_Decode (q, MAX_NN_DIGITS, privateKey->prime[1], MAX_RSA_PRIME_LEN);
        NN_Decode (dP, MAX_NN_DIGITS, privateKey->primeExponent[0], MAX_RSA_PRIME_LEN);
        NN_Decode (dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], MAX_RSA_PRIME_LEN);
        NN_Decode (qInv, MAX_NN_DIGITS, privateKey->coefficient, MAX_RSA_PRIME_LEN);
        cDigits = NN_Digits (c, MAX_NN_DIGITS);
        nDigits = NN_Digits (n, MAX_NN_DIGITS);
        pDigits = NN_Digits (p, MAX_NN_DIGITS);
    
        if (NN_Cmp (c, n, nDigits) >= 0)
            return (RE_DATA);
    
        /* Compute mP = cP^dP mod p  and  mQ = cQ^dQ mod q. (Assumes q has
        length at most pDigits, i.e., p > q.)
        */
        NN_Mod (cP, c, cDigits, p, pDigits);
        NN_Mod (cQ, c, cDigits, q, pDigits);
        NN_ModExp (mP, cP, dP, pDigits, p, pDigits);
        NN_AssignZero (mQ, nDigits);
        NN_ModExp (mQ, cQ, dQ, pDigits, q, pDigits);
    
        /* Chinese Remainder Theorem:
        m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ.
        */
        if (NN_Cmp (mP, mQ, pDigits) >= 0)
            NN_Sub (t, mP, mQ, pDigits);
        else {
            NN_Sub (t, mQ, mP, pDigits);
            NN_Sub (t, p, t, pDigits);
        }
        NN_ModMult (t, t, qInv, p, pDigits);
        NN_Mult (t, t, q, pDigits);
        NN_Add (t, t, mQ, nDigits);
    
        *outputLen = (privateKey->bits + 7) / 8;
        NN_Encode (output, *outputLen, t, nDigits);
    
        /* Zeroize sensitive information.
        */
        R_memset ((POINTER)c, 0, sizeof (c));
        R_memset ((POINTER)cP, 0, sizeof (cP));
        R_memset ((POINTER)cQ, 0, sizeof (cQ));
        R_memset ((POINTER)dP, 0, sizeof (dP));
        R_memset ((POINTER)dQ, 0, sizeof (dQ));
        R_memset ((POINTER)mP, 0, sizeof (mP));
        R_memset ((POINTER)mQ, 0, sizeof (mQ));
        R_memset ((POINTER)p, 0, sizeof (p));
        R_memset ((POINTER)q, 0, sizeof (q));
        R_memset ((POINTER)qInv, 0, sizeof (qInv));
        R_memset ((POINTER)t, 0, sizeof (t));
    
        return (0);
    }
    
    unsigned int MyStrToHex(unsigned char *pbDest, char *pszSrc)
    {
        char h1, h2;
        unsigned char s1, s2;
        int nLen = 16;
        int i = 0;
    
        for (i = 0; i < strlen(pszSrc)/2; i++)
        {
            h1 = pszSrc[2 * i];
            h2 = pszSrc[2 * i + 1];
    
            s1 = toupper(h1) - 0x30;
            if (s1 > 9)
                s1 -= 7;
    
            s2 = toupper(h2) - 0x30;
            if (s2 > 9)
                s2 -= 7;
    
            pbDest[i] = s1 * 16 + s2;
        }
        return strlen(pszSrc)/2;
    }
    unsigned int mod();
    
    void main(void)
    {
        int ret;
        unsigned int tlen,len;
    
        unsigned char plaint_buf[128]={0};
        unsigned char cipher_buf[128]={0};
        unsigned char N[256]={0};
        unsigned char D[256]={0};
        unsigned char P[256]={0};
        unsigned char Q[256]={0};
        unsigned char DP[256]={0};
        unsigned char DQ[256]={0};
        unsigned char QP[256]={0};
        unsigned char E[256]={0};
    
        const char *p="CAEB9887EB0162A1BCA52C01423ACF995234CA790B43DE9D95C0E6F41A56FAB203F4C5D976F125050F7F0376DD5474619E960F7A3C068FBB896FAB79394F3513";
        const char *q="A2D8D444F55860EEFB8FDE8D273DB48E78712CC07CB7121804848FC328E047707D55B0DD9316B3A1B372883BD87ACD5BEEEFE76E48719C6E66E4EFEAE72446E5";
        const char *dp="8747BB05475641C1286E1D562C273510E17886FB5CD7E9BE63D5EF4D66E4A72157F883E64F4B6E035FAA024F3E384D9669B95FA6D2AF0A7D064A7250D0DF78B7";
        const char *dq="6C908D834E3AEB49FD0A945E1A292309A5A0C8805324B6BAADADB52CC5EADA4AFE392093B76477C1224C5AD29051DE3D49F544F4304BBD9EEF434A9C9A182F43";
        const char *qp="20C541FEFC7EBE9F1E2CC6974A8A1CF6312380D145B38BA5786B17D65279E9777646580E09C80C7698B68D19DC263071FD7D3F01F06A20352CD1EE18163D6DC7";
        const char *n="8114F59078C3C3196E26BF502B2D68CD13FDBE683DF3A7A8F45044ADCF1335A71D64FA39FD1992E42EEE60268BECB6868B9384DFFEEB511747A4F886F63E49A1D88A8CACCC067AE28F38328A1EBB43308A4F825B5FD0DAB8D204B0712FA0438749A73939AB6375919223906BC84F3F554A8E10F27C47D6EF256951818809ABFF";
        const char *d="560DF90AFB2D2CBB9EC47F8AC7739B3362A9299AD3F7C51B4D8AD873DF6223C4BE43517BFE110C981F49956F07F32459B2625895549CE0BA2FC35059F97EDBC0472EBFEA9D1DCF8BE4ACC55278D72A05D51BB2168FE3F1577A7F7BD1484600EDDAE881AC6B92689C8A21587B61AAA90FD35ABC06A5351C8378B87968EFB9755B";
        const char *e = "00000003";
        R_RSA_PUBLIC_KEY rsa_pub_key;
        R_RSA_PRIVATE_KEY rsa_pri_key;
    
        memset(&rsa_pub_key, 0, sizeof(rsa_pub_key));
        memset(&rsa_pri_key, 0, sizeof(rsa_pri_key));
    
        //填充公钥
        rsa_pub_key.bits = 1024;
        len = MyStrToHex((char *)n,N);
        memcpy(&rsa_pub_key.modulus[MAX_RSA_MODULUS_LEN - len], N, len);
        len = MyStrToHex((char *)e,E);
        memcpy(&rsa_pub_key.exponent[MAX_RSA_MODULUS_LEN - len], E, len);
    
        printf("rsa_pub_key.modulus:%s %d \n",rsa_pub_key.modulus,MAX_RSA_MODULUS_LEN);
        printf("rsa_pub_key.modulus:%s %d \n",rsa_pub_key.modulus,MAX_RSA_MODULUS_LEN);
        printf("rsa_pub_key.exponent:%s %d \n",rsa_pub_key.exponent,MAX_RSA_MODULUS_LEN);
    
        //填充私钥
        rsa_pri_key.bits = 1024;
        len = MyStrToHex((char *)p,P);
        memcpy(&rsa_pri_key.prime[0][MAX_RSA_PRIME_LEN - len], P, len);
        len = MyStrToHex((char *)q,Q);
        memcpy(&rsa_pri_key.prime[1][MAX_RSA_PRIME_LEN - len], Q, len);
        len = MyStrToHex((char *)dp,DP);
        memcpy(&rsa_pri_key.primeExponent[0][MAX_RSA_PRIME_LEN - len], DP, len);
        len = MyStrToHex((char *)dq,DQ);
        memcpy(&rsa_pri_key.primeExponent[1][MAX_RSA_PRIME_LEN - len], DQ, len);
        len = MyStrToHex((char *)qp,QP);
        memcpy(&rsa_pri_key.coefficient[MAX_RSA_PRIME_LEN - len], QP, len);
    
        len = MyStrToHex((char *)n,N);
        memcpy(&rsa_pri_key.modulus[MAX_RSA_MODULUS_LEN - len], N, len);
        len = MyStrToHex((char *)d,D);
        memcpy(&rsa_pri_key.exponent[MAX_RSA_MODULUS_LEN - len], D, len);
        len = MyStrToHex((char *)e,E);
        memcpy(&rsa_pri_key.publicExponent[MAX_RSA_MODULUS_LEN - len], E, len);
    
        printf("rsa_pri_key.modulus:%s %d \n",rsa_pri_key.modulus,MAX_RSA_MODULUS_LEN);
        printf("rsa_pri_key.exponent:%s %d \n",rsa_pri_key.exponent,MAX_RSA_MODULUS_LEN);
        printf("rsa_pri_key.publicExponent:%s %d \n",rsa_pri_key.publicExponent,MAX_RSA_MODULUS_LEN);
        printf("rsa_pri_key.prime[0]:%s %d \n",rsa_pri_key.prime[0],MAX_RSA_PRIME_LEN);
        printf("rsa_pri_key.prime[1]:%s %d \n",rsa_pri_key.prime[1],MAX_RSA_PRIME_LEN);
        printf("rsa_pri_key.primeExponent[0]:%s %d \n",rsa_pri_key.primeExponent[0],MAX_RSA_PRIME_LEN);
        printf("rsa_pri_key.primeExponent[1]:%s %d \n",rsa_pri_key.primeExponent[1],MAX_RSA_PRIME_LEN);
        printf("rsa_pri_key.coefficient:%s %d \n",rsa_pri_key.coefficient,MAX_RSA_PRIME_LEN);
    
        memset((void *)(plaint_buf),0x00,sizeof(plaint_buf));
        //填充测试数据
        for(ret =0;ret < 128;ret++)
            plaint_buf[ret] = 10 + ret;
        printf("plaint_buf1 data:%s %ld \n",plaint_buf,sizeof(plaint_buf));
    
        //公钥加密
        ret = RSAPublicBlock(cipher_buf,&tlen,plaint_buf,128,&rsa_pub_key);
        printf("RSAPublicBlock return %d\r\n",ret);
        if(ret == 0)
        {
            printf("cipher data:%s %ld \n",cipher_buf,sizeof(cipher_buf));
        }
    
        //私钥解密
        ret = RSAPrivateBlock(plaint_buf, &tlen, cipher_buf, 128, &rsa_pri_key);
        printf("RSAPrivateBlock return %d\r\n",ret);
        if(ret == 0)
        {
            printf("plaint data:%s %d \n",plaint_buf,tlen);
        }
    
        memset(&plaint_buf, 0, sizeof(plaint_buf));
        memset(&cipher_buf, 0, sizeof(cipher_buf));
    
        //填充测试数据
        for(ret =0;ret < 128;ret++)
            plaint_buf[ret] = 20+ret;
        printf("plaint_buf2 data:%s %ld \n", plaint_buf, sizeof(plaint_buf));
    
        //私钥加密
        ret = RSAPrivateBlock(cipher_buf, &tlen, plaint_buf, 128, &rsa_pri_key);
        printf("RSAPrivateBlock return %d\r\n",ret);
        if(ret == 0)
        {
            printf("cipher data:%s %ld \n", cipher_buf, sizeof(cipher_buf));
        }
    
        //公钥解密
        ret = RSAPublicBlock(plaint_buf, &tlen, cipher_buf, 128, &rsa_pub_key);
        printf("RSAPublicBlock return %d\r\n",ret);
        if(ret == 0)
        {
            printf("cipher data:%s %ld \n",plaint_buf,sizeof(plaint_buf));
        }
    }
    
    #ifdef __cplusplus
        }
    #endif
    

     

    展开全文
  • 实现素数验证,加密解密等功能。可以对一串字符进行加密解密等操作,但运算速度较慢。
  • RSA加密算法C语言实现

    2019-11-27 20:42:07
    RSA加密算法C语言实现,int范围内可行。主要运用扩展的欧几里得算法,快速模幂算法。由于采取int四则运算,因此此版本不能进行1024bit密钥的加密。满足无限长密钥的C语言代码将稍后上传。
  • rsa加密解密算法C语言代码#include#include#include #include #include #include #define MAX 100#define LEN sizeof(struct slink)void sub(int a[MAX],int b[MAX] ,int c[MAX] );struct slink{ int bignum[MAX];/*...
    展开全文
  • RSA算法C语言加密、解密完整C语言程序
  • RSA加密算法C语言

    千次阅读 2016-11-04 20:11:26
    RSA算法原理(一) http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html RSA算法原理(二)#include int candp(int a,int b,in

    http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
    RSA算法原理(一)
    http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
    RSA算法原理(二)

    #include <stdio.h>
    int candp(int a,int b,int c)//men  m^e = k*n + r
    { 
        int r=1;
        b=b+1;
        while(b!=1)
        {
            r=r*a;
            r=r%c;
            b--;
        }
        printf("%d\n",r);
        return r;
    }
    
    void main()
    {
        int p,q,e,d,m,n,t,c,r;
        char s;
        printf("please input the p,q: ");
        scanf("%d%d",&p,&q);
        n=p*q;
        printf("the n is %3d\n",n);
        t=(p-1)*(q-1);
        printf("the t is %3d\n",t);
        printf("please input the e: ");
        scanf("%d",&e);
        if(e<1||e>t)
        {
            printf("e is error,please input again: ");
            scanf("%d",&e);
        }
        d=1;
        while(((e*d)%t)!=1)   d++;
        printf("then caculate out that the d is %d\n",d);
    
        while(1)
        {
            printf("the cipher please input 1\n");
            printf("the plain please input 2\n");
            scanf("%d",&r);
            switch(r)
            {
            case 1: printf("input the m: "); /*输入要加密的明文数字*/
                scanf("%d",&m);
                c=candp(m,e,n);
                printf("the cipher is %d\n",c);break;
            case 2: printf("input the c: "); /*输入要解密的密文数字*/
                scanf("%d",&c);
                m=candp(c,d,n);
                printf("the cipher is %d\n",m);break;
            }
        }
        getch();
    }
    
    展开全文
  • rsa算法c语言实现

    2018-05-10 13:44:53
    基于C语言实现的RSA算法,实现过程基本和实验原理保持一致,由于编写过程一开始并没有进行实用性考虑,所以该算法输入仅支持固定位数的数字,但是通过适当修改可以支持char或者string类型的内容输入——buaa-albert
  • RSA算法C语言中的实现,RSA加密算法在C语言中的的实现
  • 信息安全RSA算法实现 C语言 可以运行
  • 非对称加密算法,RSA算法C语言代码实现,带测试demo
  • rsa 算法的c实现,希望对各位有所帮助
  • rsa加密算法C语言编写

    2010-05-28 17:25:31
    C语言编写的rsa加密算法,这程序我自己写的,不能对较大的数加密,希望大家多多指点。
  • 从第三方密码学库中抽离出来的RSA算法,去掉了不必要的依赖。效率非常好,可用于实际的工作中! 测试数据经过两个以上第三方密码学库验证,确保测试数据正确性。 test.cpp中包含精心编写的的测试用例,关键之处都有...
  • RSA加密算法 C语言

    2009-04-05 09:28:12
    学校上机课做的一个小算法 其中需要gmp算法包 网上可以找的到

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 244
精华内容 97
关键字:

rsa算法c语言

c语言 订阅