1. 程式人生 > >RSA演算法C語言實現

RSA演算法C語言實現

RSA演算法在資料加密中是最常用的,這裡需要兩組祕鑰,一組私鑰,一組公鑰,往往是用私鑰加密的資料傳輸到終端用公鑰解密,然後用公鑰加密的資料傳回去用私鑰解密。
下邊是加解密的C語言的原始碼:

/* RSA.C - RSA routines for RSAREF  
 */   

/* Copyright (C) RSA Laboratories, a division of RSA Data Security,  
     Inc., created 1991. All rights reserved.  
 */   

#include "rsa.h" 
#include <string.h>
#include <stdlib.h> #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); }

標頭檔案rsa.h

/* RSAREF.H - header file for RSAREF cryptographic toolkit 
 */ 

/* Copyright (C) RSA Laboratories, a division of RSA Data Security, 
     Inc., created 1991. All rights reserved. 
 */ 

#ifndef _RSA_H_ 
#define _RSA_H_ 1 


#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 
            
           

相關推薦

RSA演算法C語言實現

RSA演算法在資料加密中是最常用的,這裡需要兩組祕鑰,一組私鑰,一組公鑰,往往是用私鑰加密的資料傳輸到終端用公鑰解密,然後用公鑰加密的資料傳回去用私鑰解密。 下邊是加解密的C語言的原始碼: /* RSA.C - RSA routines for RSAR

SHA-1演算法C語言實現

> 程式碼轉載自:https://blog.csdn.net/testcs_dn/article/details/25771377?locationNum=13&fps=1 > 感謝博主分享 #include<stdio.h> void creat_w(uns

頁面置換演算法——最近最久未使用演算法(c語言實現)

作業系統實驗:用C語言程式設計實現最近最久未使用置換演算法(LRU) 最近最久未使用置換演算法(LRU),全稱Least Recently Used,是一種頁面置換演算法。 對於在記憶體中但又不用的資料塊(記憶體塊)叫做LRU,作業系統會根據哪些資料屬於LRU而將其移出記憶體而騰出空間來載入另外

建立雙向連結串列的演算法——C語言實現

建立雙向連結串列的演算法——C語言實現 雙向連結串列也叫雙鏈表,是連結串列的一種,它的每個節點包含兩個指標,分別指向直接後繼和直接前驅(頭節點的前驅指空,尾節點的後繼指空)。所以,從雙向連結串列中的任意一個非前驅非後繼節點開始,都能很方便地訪問它的前驅和後繼節點。 實際上如果熟練掌握了單向連

差分進化演算法 C語言實現

之前的一篇中貼出了自己研究生期間C實現的基本粒子群演算法,執行速度顯然要比其他的高階語言快,這也是各個程式語言之間的差別,現在對於曾經輝煌過的差分進化演算法進行C語言實現。變異策略採用DE/rand/1,這個是最常見的。有錯誤之處請之處。 /***************D

氣泡排序演算法C語言實現

第一部分   排序方法介紹 常用的排序方法:氣泡排序,選擇排序,插入排序及希爾排序等。        氣泡排序是常用的一種排序方法,其基本方法就是逐次比較。即一次比較兩個數,若它們的順序錯誤,則交換;重複進行,知道沒有需要交換為止。 以升序排序為例:        1.

MD5加密演算法C語言實現

md5.h #ifndef MD5_H #define MD5_H typedef struct { unsigned int count[2]; unsigned int state[4]; unsigned char buffe

磁碟排程演算法C語言實現

最短尋道時間優先(SSTF)演算法。要求訪問的磁軌,與當前磁頭所在的磁軌距離最近,以使每次的尋道時間最短。掃描排程(SCAN)演算法。該演算法不僅考慮到欲訪問的磁軌與當前磁軌間的距離,更優先考慮的是磁頭當前的移動方向。例如,當磁頭正在自裡向外移動時,SCAN演算法所考慮的下一

非常值得一看—九種濾波演算法C語言實現

關注“嵌入式軟體開發學習圈”免費獲取更多學習教程 今天帶著大家學習濾波演算法c語言(九種濾波演算法)實現,以及程式碼,大家可以學習瞭解下。。。。 1.限幅濾波演算法(程式判斷濾波演算法) 方法解析: 根據經驗判斷,確定兩次取樣允許的最

作業排程之先來先服務演算法C語言實現

程式碼如下 /*    @author WellsLiu    @url liuyanzhao.com*/#include"stdio.h"#include"stdlib.h"typedef st

處理機排程演算法C語言實現(註釋得當!!)

/* created by herbert on 10 Nov */ #include <iostream> #include <queue> #include <algorithm> #include <c

最短路徑之Dijkstra演算法 C語言實現

Dijkstra演算法(單源點路徑演算法,要求:圖中不存在負權值邊): 步驟: a.  初始時,S只包含源點,即S={v},v的距離為0。U包含除v外的其他頂點,即: U={其餘頂點},若v與U中頂點u有邊,則u的距離設定為相應的權值,若u v之間不存在邊,則    

SHA-256演算法 C語言實現

#include <stdio.h> #include <stdlib.h> #define SHA256_ROTL(a,b) (((a>>(32-b))&(0x7fffffff>>(31-b)))|(a<<

哈夫曼壓縮演算法C語言實現——步驟,詳細註釋原始碼

哈夫曼壓縮演算法的詳細實現步驟: 1、定義哈夫曼樹節點,用結構體。 2、利用C語言檔案讀寫,統計字元個數。 3、根據字元個數建立哈夫曼樹(不懂haffman資料結構的自己查下資料,我這裡就不再重複了) 4、根據哈夫曼樹為每個出現的字元編碼 5、壓縮:這裡涉及到位操作,用ch

爐石傳說爆牌魚斬殺演算法C語言實現

#include <stdio.h> int main() {     printf("請輸入敵方血量:\n");     int difangxue;     scanf("%d",&difangxue);     printf("請輸入自己血量:

九大排序演算法-C語言實現及詳解

概述 排序有內部排序和外部排序,內部排序是資料記錄在記憶體中進行排序,而外部排序是因排序的資料很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。 我們這裡說說八大排序就是內部排序。     當n較大,則應採用時間複雜度為O(nlog2n)的排序方法:快

Dijkstra演算法 c語言實現

 Dijkstra(迪傑斯特拉)演算法是典型的最短路徑路由演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。Dijkstra演算法能得出最短路徑的最優解,但由於它遍歷計算的節點很多,所以效率低。   Dijk

dijstra演算法 c語言實現

看來群的作用真的很大啊 剛才為了一下,發現自己的抽象思維能力簡直為0 總以為沒有辦法處理集合,然後群裡面的人說可以用bool 陣列,然後研究了一下,果然可以 演算法描述的時候說集合的並啊,減啊,在c語言裡,用個bool陣列就可以, 剛開始初始化為false 然後進來一個t

簡單的K-means演算法C語言實現程式碼

K-means演算法是很典型的基於距離的聚類演算法,採用距離作為相似性的評價指標,即認為兩個物件的距離越近,其相似度就越大。該演算法認為簇是由距離靠近的物件組成的,因此把得到緊湊且獨立的簇作為最終目標。 演算法過程如下: 1)從N個樣本隨機選取K個樣本作為質心 2)對剩餘