📄 r_enhanc.c
字号:
/*
R_ENHANC.C - cryptographic enhancements for RSAEURO
Copyright (c) J.S.A.Kapp 1994 - 1995.
RSAEURO - RSA Library compatible with RSAREF(tm) 2.0.
All functions prototypes are the Same as for RSAREF(tm).
To aid compatiblity the source and the files follow the
same naming comventions that RSAREF(tm) uses. This should aid
direct importing to your applications.
This library is legal everywhere outside the US. And should
NOT be imported to the US and used there.
All Trademarks Acknowledged.
Cryptographic Enhancements.
Revision history
0.90 First revision, initial production of file.
0.91 Second revision, altered to incorporate the addition of
the SHS hashing algorithm to the toolkit. Waiting for OBJ ID
for SHS Signature.
0.92 Third revision, modified Digest, Signing and Verifying
routines with improved error checking, to prevent SHS digest
being used for signing data. R_VerifyFinal altered to check
that same digest used in original signature was used in verify
doesn't verify signature if they don't match.
1.02 Fourth revision, R_SealUpdate Bug fixed, Bug Reported by
Anders Heerfordt <i3683@dc.dk>.
*/
#include "rsaeuro.h"
#include "r_random.h"
#include "rsa.h"
/* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 or 4 (for MD2/MD5/MD4),
then DIGEST_INFO_B, then 16-byte message digest. */
/* Using the Original RSAREF/PKCS Object Indentifier, for signatures */
static unsigned char DIGEST_INFO_A[] = {
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x02
};
#define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A)
static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };
#define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B)
#define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16)
static unsigned char *PADDING[] = {
(unsigned char *)"", (unsigned char *)"\01", (unsigned char *)"\02\02",
(unsigned char *)"\03\03\03", (unsigned char *)"\04\04\04\04",
(unsigned char *)"\05\05\05\05\05",
(unsigned char *)"\06\06\06\06\06\06",
(unsigned char *)"\07\07\07\07\07\07\07",
(unsigned char *)"\08\08\08\08\08\08\08\08"
};
#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN
static void R_EncodeDigestInfo PROTO_LIST((unsigned char *, int, unsigned char *));
static int R_CheckDigestInfo PROTO_LIST ((unsigned char *, unsigned char *));
/* encrypt prototypes */
static int CipherInit PROTO_LIST((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int));
static void EncryptBlk PROTO_LIST((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int));
static void RestartCipher PROTO_LIST((R_ENVELOPE_CTX *));
int R_DigestInit(context, digesttype)
R_DIGEST_CTX *context; /* new context */
int digesttype; /* message-digest algorithm */
{
context->digestAlgorithm = digesttype;
switch(digesttype) {
case DA_SHS:
SHSInit(&context->context.shs);
break;
case DA_MD2:
MD2Init(&context->context.md2);
break;
case DA_MD4:
MD4Init(&context->context.md4);
break;
case DA_MD5:
MD5Init(&context->context.md5);
break;
default:
return(RE_DIGEST_ALGORITHM);
}
return(IDOK);
}
int R_DigestUpdate(context, partIn, partInLen)
R_DIGEST_CTX *context; /* context */
unsigned char *partIn; /* next data part */
unsigned int partInLen; /* length of next data part */
{
switch(context->digestAlgorithm) {
case DA_SHS:
SHSUpdate(&context->context.shs, partIn, partInLen);
break;
case DA_MD2:
MD2Update(&context->context.md2, partIn, partInLen);
break;
case DA_MD4:
MD4Update(&context->context.md4, partIn, partInLen);
break;
case DA_MD5:
MD5Update(&context->context.md5, partIn, partInLen);
break;
default:
return(RE_DIGEST_ALGORITHM);
}
return(IDOK);
}
int R_DigestFinal(context, digest, digestLen)
R_DIGEST_CTX *context; /* context */
unsigned char *digest; /* message digest */
unsigned int *digestLen; /* length of message digest */
{
*digestLen = context->digestAlgorithm == DA_SHS ? 20 : 16;
switch(context->digestAlgorithm) {
case DA_SHS:
SHSFinal(&context->context.shs); /* doesn't output as chars */
break;
case DA_MD2:
MD2Final(digest, &context->context.md2);
break;
case DA_MD4:
MD4Final(digest, &context->context.md4);
break;
case DA_MD5:
MD5Final(digest, &context->context.md5);
break;
default:
return(RE_DIGEST_ALGORITHM);
}
return(IDOK);
}
/* Signing a file using SHS is not allowed for now */
int R_SignInit(context, digesttype)
R_SIGNATURE_CTX *context; /* new context */
int digesttype; /* message-digest algorithm */
{
return((digesttype == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digesttype));
}
int R_SignUpdate(context, partIn, partInLen)
R_SIGNATURE_CTX *context; /* context */
unsigned char *partIn; /* next data part */
unsigned int partInLen; /* length of next data part */
{
return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen));
}
int R_SignFinal(context, signature, signatureLen, privateKey)
R_SIGNATURE_CTX *context; /* context */
unsigned char *signature; /* signature */
unsigned int *signatureLen; /* length of signature */
R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */
{
int status;
unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN];
unsigned int digestLen;
if(context->digestContext.digestAlgorithm == DA_SHS)
status = RE_DIGEST_ALGORITHM;
else {
if((status = R_DigestFinal(&context->digestContext, digest, &digestLen)) == 0) {
R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest);
if(RSAPrivateEncrypt(signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey) != 0) {
status = RE_PRIVATE_KEY;
}else{
/* Reset for another verification. */
R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm);
}
}
/* Clear sensitive information. */
R_memset(digest, 0, sizeof(digest));
R_memset(digestInfo, 0, sizeof(digestInfo));
}
return(status);
}
int R_VerifyInit(context, digestAlgorithm)
R_SIGNATURE_CTX *context; /* new context */
int digestAlgorithm; /* message-digest algorithm */
{
return((digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digestAlgorithm));
}
int R_VerifyUpdate(context, partIn, partInLen)
R_SIGNATURE_CTX *context; /* context */
unsigned char *partIn; /* next data part */
unsigned int partInLen; /* length of next data part */
{
return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen));
}
int R_VerifyFinal(context, signature, signatureLen, publicKey)
R_SIGNATURE_CTX *context; /* context */
unsigned char *signature; /* signature */
unsigned int signatureLen; /* length of signature */
R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */
{
int status;
unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN],
originalDigestInfo[MAX_SIGNATURE_LEN];
unsigned int originalDigestInfoLen, digestLen;
status = 0;
if(signatureLen > MAX_SIGNATURE_LEN)
status = RE_LEN;
if(context->digestContext.digestAlgorithm == DA_SHS)
status = RE_DIGEST_ALGORITHM;
if(!status) {
if((status = R_DigestFinal (&context->digestContext, digest, &digestLen)) == 0) {
R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest);
if(RSAPublicDecrypt(originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, publicKey) != 0) {
status = RE_PUBLIC_KEY;
}else{ /* Check the digest out */
if((originalDigestInfoLen != DIGEST_INFO_LEN) || R_CheckDigestInfo(originalDigestInfo, digestInfo) || (R_memcmp((POINTER)originalDigestInfo, (POINTER)digestInfo, DIGEST_INFO_LEN)))
status = RE_SIGNATURE;
else
/* Reset for another verification. */
R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm);
}
}
/* Clear sensitive information. */
R_memset(digest, 0, sizeof(digest));
R_memset(digestInfo, 0, sizeof(digestInfo));
R_memset(originalDigestInfo, 0, sizeof(originalDigestInfo));
}
return(status);
}
/* Caller must ASCII encode the encrypted keys if required. */
int R_SealInit(context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys,
encryptionAlgorithm, randomStruct)
R_ENVELOPE_CTX *context; /* new context */
unsigned char **encryptedKeys; /* encrypted keys */
unsigned int *encryptedKeyLens; /* lengths of encrypted keys */
unsigned char iv[8]; /* initialization vector */
unsigned int publicKeyCount; /* number of public keys */
R_RSA_PUBLIC_KEY **publicKeys; /* public keys */
int encryptionAlgorithm; /* data encryption algorithm */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
int status;
unsigned char key[24];
unsigned int keyLen, i;
context->encryptionAlgorithm = encryptionAlgorithm;
keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24;
if((status = R_GenerateBytes (key, keyLen, randomStruct)) == 0) {
if((status = R_GenerateBytes (iv, 8, randomStruct)) == 0) {
if(encryptionAlgorithm == EA_DES_EDE2_CBC)
/* Make both E keys the same */
R_memcpy ((POINTER)(key + 16), (POINTER)key, 8);
if((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) == 0) {
for(i = 0; i < publicKeyCount; ++i) {
if(RSAPublicEncrypt(encryptedKeys[i], &encryptedKeyLens[i], key, keyLen,
publicKeys[i], randomStruct)) {
status = RE_PUBLIC_KEY;
break;
}
}
}
if(status == 0)
context->bufferLen = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -