⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p1363.c

📁 miracl-大数运算库,大家使用有什么问题请多多提意见
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 
 * MIRACL-based implementation of the IEEE 1363 standard 
 * Version 1.4 December 2005
 *
 * NEW 1.1 - Elliptic curve points now stored in a single OCTET as recommended
 *           in P1363a. Such octets will be 2*fs+1 in length, where fs is
 *           the field size. If compression is used they may be fs+1
 *
 * NEW 1.2 - Auxiliary functions completely re-written
 *           More primitives and functions implemented
 *           New mirvar_mem function used for extra speed 
 *
 * NEW 1.3 - Cryptographically strong RNG interface improved
 *
 * Implements most of the cryptographic primitives, message encoding methods, 
 * key derivation functions and auxiliary functions necessary for realising the 
 * recommended methods. Note that GF(p) and GF(2^m) Elliptic curves are
 * treated seperately.
 *
 * See the IEEE 1363 documentation for details
 * http://grouper.ieee.org/groups/1363/index.html
 * This IS the documentation for this implementation. Each P1363 function
 * has the same name, and same inputs/outputs as those described in the 
 * official 1363 documentation.
 *
 * The user is responsible for the initialisation and maintainance of 
 * "Octet strings" which store Cryptographic keys and application info.
 * These octet strings store big numbers in binary, from MSB down to LSB
 * NOTE:- Leading zeros can be suppressed! Use OCTET_PAD() to insert leading
 * zeros to make an octet a particular length, e.g. 20 bytes, 160 bits.
 * 
 * An instance of a Cryptographically Strong Random Number Generator
 * must be created and initialised by the user with
 * raw random data. This doesn't have to be high quality (e.g. mouse movement 
 * coordinates), but there must be enough of it for it to be unguessable. 
 * It is subsequently maintained internally by the system
 * The secure random number generation method used is based on that described 
 * in ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf
 *
 * The above is the recommended approach. 
 * Alternatvely when generating a key pair a random number can be specified 
 * directly as a private key, and this internal system by-passed. 
 * 
 * Domain and Public/Private key data is stored in structures defined in 
 * p1363.h. The first parameter in each function is a pointer to a function 
 * which will be called during time-consuming calculations - e.g. a Windows 
 * message pump. Negative return values indicate an error - see p1363.h for 
 * definitions. Most common MIRACL errors are mapped to these values.
 * Unlikely MIRACL errors are returned as -(1000+MEC), where MEC
 * is the MIRACL Error Code (see miracl.h)
 *
 * quick start:-
 * cl /O2 test1363.c p1363.c ms32.lib
 *
 * Recommended for use with a (32-bit) MIRACL library built 
 * from a mirdef.h file that looks something like this:-
 *
 * #define MIRACL 32
 * #define MR_LITTLE_ENDIAN
 * #define mr_utype int
 * #define MR_IBITS 32
 * #define MR_LBITS 32
 * #define mr_unsign32 unsigned int
 * #define MR_STRIPPED_DOWN
 * #define MR_GENERIC_MT
 * #define mr_dltype __int64
 * #define mr_unsign64 unsigned __int64
 * #define MAXBASE ((mr_small)1<<(MIRACL-1))
 *
 * Note that this is a multi-threaded build, ideal for a Cryptographic DLL
 * The compiler may need a multithreaded flag set (/MT ??) 
 *
 * The miracl instance variable ERCON is set to TRUE in each routine, so 
 * MIRACL does not attempt to report an error. Instead the variable ERNUM 
 * latches the last error, and if set causes each subsequent routine to 
 * "fall through".  
 *
 * Octet strings are not tested for overflow. In fact overflow will not 
 * happen as octets will be truncated - so buffer overflow attacks against 
 * this code will not succeed. To avoid unintentional overflow its best to 
 * initialise the length of most octets to that recommended and returned by 
 * the XXX_DOMAIN_INIT() routines. Note however that elliptic curve point  
 * octets should be initialised to "twice this length plus 1" (or only "this 
 * length plus 1" if compression is used)
 *
 * A test driver main() function is provided in test1363.c to test all the 
 * functions, and to implement five of the recommended methods, IFSSA, IFSSR, 
 * DLSSR, DLSSR-PV and ECIES 
 *
 * In Win32 MS C:-
 * cl /O2 /MT test1363.c p1363.c miracl.lib  /link /NODEFAULTLIB:libc.lib
 * and run the executable
 *
 * test1363         ; 
 * test1363 -c      ; uses EC point compression
 * test1363 -p      ; uses precomputation for signature
 * test1363 -c -p   ; uses both precomputation and EC point compression
 *
 * To create a Windows P1363 DLL, compile as 
 * cl /O2 /W3 /MT /DMR_P1363_DLL /LD p1363.c miracl.lib /link /NODEFAULTLIB:libc.lib
 * To run the test program to use the DLL, compile as
 * cl /O2 /MT /DMR_P1363_DLL test1363.c p1363.lib
 * 
 * Discrete Logarithm/GF(p) Elliptic Curve/GF(2^m) Elliptic Curve Domain 
 * details are read from the files common.dss, common.ecs and common2.ecs 
 * respectively. Suitable files are included in the standard MIRACL 
 * distribution. You can generate your own using for example the utilities 
 * dssetup.cpp, schoof.cpp and schoof2.cpp. But make sure that the group order
 * in each case is at least 160-bits, or the demo may fail.
 *
 * Note that for a full 1363 implementation various simple message-encoding 
 * regimes must be also implemented, as described in the P1363 and P1363a 
 * documentation. Many of these are now implemented here. Also suitable hashing
 * functions must be available. The SHA1/SHA256/SHA384 and SHA512 algorithms 
 * are recommended, and implemented in MIRACL 
 *
 * Note that some of the message encoding functions can take input from a file
 * rather than from a string. This is convenient for example if "signing" a 
 * large document. In these cases the parameters are typically "octet *x,FILE 
 * *fp", in which case either an OCTET string x can be specified OR a 
 * filename, but not both.
 *
 * Version 1.4
 * Miracl STATIC (no-heap version) supported. However octets (which are oftern variable length)
 * must still be allocated from the heap. 
 * NOTE: Precomputation not directly supported in this mode 
 *
 * NOTE: It would be typical to break this file up and just use the parts that are needed
 * (For example if using Elliptic curve methods only, then the size of structures could be much smaller)
 *
 * Copyright (c) 2000-2004 Shamus Software Ltd.
 */

/* define this next to create Windows DLL */   

/* #define MR_1363_DLL */

#ifdef MR_P1363_DLL
#define P1363_DLL
#endif

#include <stdio.h>
#include <stdlib.h>
#include "p1363.h"

/* Hash IDs for supported EMSA3 hash functions. <hashIDlen>,<hash ID> */

static unsigned char SHA160ID[]={15,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14};
static unsigned char SHA256ID[]={19,0x30,0x21,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
static unsigned char SHA384ID[]={19,0x30,0x21,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
static unsigned char SHA512ID[]={19,0x30,0x21,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};

/* IDs for SHA1,RIPEMD,SHA256,SHA384 and SHA512 */
/* NOTE ripemd is not implemented               */

static unsigned char sha_id[]={0x33,0x31,0x34,0x36,0x35};

/* Internal functions */

static long filelength(FILE *fp)
{ /* return file length in reasonably portable fashion */
    long len;
    fseek(fp,0,SEEK_END);
    len=ftell(fp);
    fseek(fp,0,SEEK_SET);
    return len;
}

static void OS2FEP(_MIPD_ octet *s,big w)
{ /* internal:- converts from octet to big format */
    bytes_to_big(_MIPP_ s->len,s->val,w);
}

static void convert_big_octet(_MIPD_ big w,octet *s)
{ /* internal:- converts from big integer to octet format */
    s->len=(oltype)big_to_bytes(_MIPP_ 0,w,s->val,FALSE);
}

static void FE2OSP(_MIPD_ big w,int fsize,octet *s)
{ /* internal:- converts from big to field element format */
    s->len=(oltype)big_to_bytes(_MIPP_ fsize,w,s->val,TRUE);
}

static void EC2OSP(_MIPD_ big x,big y,int cbit,BOOL compressed,int fsize,octet *s)
{ /* internal:- converts from (x,y) to octet string */
    s->len=1; 
    if (compressed) s->val[0]=2+cbit; 
    else            s->val[0]=6+cbit;     /* hybrid */
    s->len+=(oltype)big_to_bytes(_MIPP_ fsize,x,&(s->val[1]),TRUE);
    if (!compressed) s->len+=(oltype)big_to_bytes(_MIPP_ fsize,y,&(s->val[fsize+1]),TRUE);
}

static BOOL OS2ECP(_MIPD_ octet *s,big x,big y,int fsize,int *bit)
{ /* converts from octet string to (x,y) point */

    bytes_to_big(_MIPP_ fsize,&(s->val[1]),x);
    if (s->val[0]&4)
    { /* uncompressed ..but don't put a y if not required */
        if(y!=NULL) bytes_to_big(_MIPP_ fsize,&(s->val[fsize+1]),y);
        return FALSE;
    }   
    else
    { /* compressed */
        *bit=s->val[0]&1;
        return TRUE;
    } 
}

/* return output length of hash function in bytes, also hash function input 
   block size if desired */

static int hash_params(int hash_type,int *block)
{
    switch (hash_type)
    {
    case SHA1:
        if (block!=NULL) *block=64;
        return 20;
    case SHA256:
        if (block!=NULL) *block=64;
        return 32;
#ifdef mr_unsign64
    case SHA384:
        if (block!=NULL) *block=128;
        return 48;
    case SHA512:
        if (block!=NULL) *block=128;
        return 64;   
#endif
    default:
        break;
    }
    return 0;
}

/*** Basic Octet string maintainance routines  ***/
/* initialize an octet string                    */
/* make it impossible to write beyond max length */

P1363_API BOOL OCTET_INIT(octet *w,int bytes)
{
    w->len=0;
    w->max=bytes; 
    w->val=(char *)malloc(bytes);
    if (w->val!=NULL) return TRUE;
    else              return FALSE; 
}

/* clear an octet string */

P1363_API void OCTET_CLEAR(octet *w)
{
    int i;
    for (i=0;i<w->len;i++) w->val[i]=0;
    w->len=0;
}

/* XOR m with all of x */

P1363_API void OCTET_XOR_BYTE(octet *x,int m)
{
    int i;
    for (i=0;i<x->len;i++) x->val[i]^=m;
}

/* XOR common bytes of x with y */

P1363_API void OCTET_XOR(octet *x,octet *y)
{ /* xor first x->len bytes of y */

    int i;
    for (i=0;i<x->len && i<y->len;i++)
    {
        y->val[i]^=x->val[i];
    }
}

/* clear an octet */

P1363_API void OCTET_EMPTY(octet *w)
{
    w->len=0;
}

/* copy an octet string - truncates if no room */

P1363_API void OCTET_COPY(octet *x,octet *y)
{
    int i;
    OCTET_CLEAR(y);
    y->len=x->len;
    if (y->len>y->max) y->len=y->max;

    for (i=0;i<y->len;i++)
        y->val[i]=x->val[i];
}

/* compare 2 octet strings. 
 * If x==y return TRUE, else return FALSE */ 

P1363_API BOOL OCTET_COMPARE(octet *x,octet *y)
{
    int i;
    if (x->len>y->len) return FALSE;
    if (x->len<y->len) return FALSE;
    for (i=0;i<x->len;i++)
    {
        if (x->val[i]!=y->val[i]) return FALSE;
    }
    return TRUE;
}

/* check are first n bytes the same */

P1363_API BOOL OCTET_NCOMPARE(octet *x,octet *y,int n)
{
    int i;
    if (n>y->len || n>x->len) return FALSE;
    for (i=0;i<n;i++)
    {
        if (x->val[i]!=y->val[i]) return FALSE;
    }
    return TRUE;
}

/* Pads an octet with leading zeros - returns FALSE if not enough room */

P1363_API BOOL OCTET_PAD(octet *x,int len)
{
    int i,d;
    if (len>x->max || x->len>len) return FALSE;
    if (len==x->len) return TRUE;
    d=len - x->len;
    for (i=len-1;i>=d;i--)
        x->val[i]=x->val[i-d];

    for (i=0;i<d;i++) x->val[i]=0;
    x->len=(oltype)len;
    return TRUE;
}

/* Shift octet to the left by n bytes. Leftmost bytes disappear  */

P1363_API void OCTET_SHIFT_LEFT(octet *x,int n)
{
    int i;
    if (n>=x->len)
    {
        x->len=0;
        return;
    }
    x->len-=n;
    for (i=0;i<x->len;i++)
        x->val[i]=x->val[i+n];
}    

/* truncates x to n bytes and places the rest in y (if y is not NULL) */

P1363_API void OCTET_CHOP(octet *x,int n,octet *y)
{
    int i;
    if (n>=x->len)
    {
        if (y!=NULL) y->len=0;
        return;
    }
    if (y!=NULL) y->len=x->len-n;
    x->len=n; 

    if (y!=NULL)
    {
        for (i=0;i<y->len && i<y->max;i++) y->val[i]=x->val[i+n];
    }
}

/* Concatenates two octet strings */

P1363_API void OCTET_JOIN_OCTET(octet *x,octet *y)
{ /* y=y || x */
    int i,j;
    if (x==NULL) return;

    for (i=0;i<x->len;i++)
    {
        j=y->len+i;
        if (j>=y->max)
        {
            y->len=y->max;
            return;
        }
        y->val[j]=x->val[i];
    }
    y->len+=x->len;
}

/* OCTET_JOIN_LONG primitive */
/* appends long x to OCTET string of length len */
/* if more than len bytes required, string is increased > len */

P1363_API void OCTET_JOIN_LONG(long x, int len,octet *y)
{
   int i,j,n;
   n=y->len+len;
   if (n>y->max || len<=0) return;
   for (i=y->len;i<n;i++) y->val[i]=0; 
   y->len=n;

   i=len;
   while (x>0)
   {
       if (i==0)
       {
           for (j=y->len;j>0;j--) y->val[j]=y->val[j-1];
           y->len++;
           if (y->len>y->max) break;
           i=1;
       }
       i--;
       y->val[i]=x%256;
       x/=256;
   }    
}

/* Convert C string to octet format - truncates if no room  */

P1363_API void OCTET_JOIN_STRING(char *s,octet *y)
{
    int i,j;
    i=y->len;
    j=0;
    while (s[j]!=0 && i<y->max)
    {
        y->val[i]=s[j];
        y->len++;
        i++;  j++;
    }
}

/* Append binary string to octet - truncates if no room */

P1363_API void OCTET_JOIN_BYTES(char *b,int len,octet *y)
{
    int i,j;
    i=y->len;
    for (j=0;j<len && i<y->max;j++) 
    {
        y->val[i]=b[j];
        y->len++;
        i++;
    }
}

/* Append byte to octet rep times */

P1363_API void OCTET_JOIN_BYTE(int ch,int rep,octet *y)
{
    int i,j;
    i=y->len;
    for (j=0;j<rep && i<y->max;j++) 
    {
        y->val[i]=ch;
        y->len++;
        i++;
    }
}

/* Copy len random bytes into octet */

P1363_API void OCTET_RAND(csprng *RNG,int len,octet *x)
{
    int i;
    if (len>x->max) len=x->max;
    x->len=len;

    for (i=0;i<len;i++) x->val[i]=strong_rng(RNG);
}

/* Output an octet string (Debug Only) */

P1363_API void OCTET_OUTPUT(octet *w)
{
    int i;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -