📄 rsautl.c
字号:
#ifndef OPENSSL_NO_RSA
#include "apps.h"
#include <string.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#define RSA_SIGN 1
#define RSA_VERIFY 2
#define RSA_ENCRYPT 3
#define RSA_DECRYPT 4
#define KEY_PRIVKEY 1
#define KEY_PUBKEY 2
#define KEY_CERT 3
int rsautl_main(int argc, char **argv,char *inbuf,int *inlen,char *outbuf,int *outlen)
{
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL;
char *infile = NULL, *outfile = NULL;
#ifndef OPENSSL_NO_ENGINE
char *engine = NULL;
#endif
char *keyfile = NULL;
char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
int keyform = FORMAT_PEM;
char need_priv = 0, badarg = 0, rev = 0;
char hexdump = 0, asn1parse = 0;
X509 *x;
EVP_PKEY *pkey = NULL;
RSA *rsa = NULL;
unsigned char *rsa_in = NULL, *rsa_out = NULL, pad;
char *passargin = NULL, *passin = NULL;
int rsa_inlen, rsa_outlen = 0;
int keysize;
int ret = 1;
if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
if (!load_config(bio_err, NULL))
goto end;
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
pad = RSA_PKCS1_PADDING;
while(argc >= 1)
{
if (!strcmp(*argv,"-in"))
{
if (--argc < 1) badarg = 1;
infile= *(++argv);
}
else if (!strcmp(*argv,"-out"))
{
if (--argc < 1) badarg = 1;
outfile= *(++argv);
}
else if(!strcmp(*argv, "-inkey"))
{
if (--argc < 1) badarg = 1;
keyfile = *(++argv);
}
else if (!strcmp(*argv,"-passin"))
{
if (--argc < 1) badarg = 1;
passargin= *(++argv);
}
else if (strcmp(*argv,"-keyform") == 0)
{
if (--argc < 1) badarg = 1;
keyform=str2fmt(*(++argv));
#ifndef OPENSSL_NO_ENGINE
}
else if(!strcmp(*argv, "-engine"))
{
if (--argc < 1) badarg = 1;
engine = *(++argv);
#endif
}
else if(!strcmp(*argv, "-pubin"))
{
key_type = KEY_PUBKEY;
}
else if(!strcmp(*argv, "-certin"))
{
key_type = KEY_CERT;
}
else if(!strcmp(*argv, "-asn1parse")) asn1parse = 1;
else if(!strcmp(*argv, "-hexdump")) hexdump = 1;
else if(!strcmp(*argv, "-raw")) pad = RSA_NO_PADDING;
else if(!strcmp(*argv, "-oaep")) pad = RSA_PKCS1_OAEP_PADDING;
else if(!strcmp(*argv, "-ssl")) pad = RSA_SSLV23_PADDING;
else if(!strcmp(*argv, "-pkcs")) pad = RSA_PKCS1_PADDING;
else if(!strcmp(*argv, "-x931")) pad = RSA_X931_PADDING;
else if(!strcmp(*argv, "-rev")) rev = 1;
else if(!strcmp(*argv, "-sign"))
{
rsa_mode = RSA_SIGN;
need_priv = 1;
}
else if(!strcmp(*argv, "-verify")) rsa_mode = RSA_VERIFY;
else if(!strcmp(*argv, "-encrypt"))
{
rsa_mode = RSA_ENCRYPT;
}
else if(!strcmp(*argv, "-decrypt"))
{
rsa_mode = RSA_DECRYPT;
need_priv = 1;
}
else badarg = 1;
if(badarg)
{
goto end;
}
argc--;
argv++;
}
if(need_priv && (key_type != KEY_PRIVKEY)) {
BIO_printf(bio_err, "A private key is needed for this operation\n");
goto end;
}
#ifndef OPENSSL_NO_ENGINE
e = setup_engine(bio_err, engine, 0);
#endif
if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
/* FIXME: seed PRNG only if needed */
app_RAND_load_file(NULL, bio_err, 0);
switch(key_type)
{
case KEY_PRIVKEY:
pkey = load_key(bio_err, keyfile, keyform, 0,
passin, e, "Private Key");
break;
case KEY_PUBKEY:
pkey = load_pubkey(bio_err, keyfile, keyform, 0,
NULL, e, "Public Key");
break;
case KEY_CERT:
x = load_cert(bio_err, keyfile, keyform,
NULL, e, "Certificate");
if(x)
{
pkey = X509_get_pubkey(x);
X509_free(x);
}
break;
}
if(!pkey)
{
return 1;
}
rsa = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
if(!rsa)
{
BIO_printf(bio_err, "Error getting RSA key\n");
ERR_print_errors(bio_err);
goto end;
}
if(infile)
{
if(!(in = BIO_new_file(infile, "rb")))
{
BIO_printf(bio_err, "Error Reading Input File\n");
ERR_print_errors(bio_err);
goto end;
}
}
if(outfile)
{
if(!(out = BIO_new_file(outfile, "wb")))
{
BIO_printf(bio_err, "Error Reading Output File\n");
ERR_print_errors(bio_err);
goto end;
}
}
/* else
{
out = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
{
BIO *tmpbio = BIO_new(BIO_f_linebuffer());
out = BIO_push(tmpbio, out);
}
#endif
}
*/
keysize = RSA_size(rsa);
rsa_in = OPENSSL_malloc(keysize * 2);
rsa_out = OPENSSL_malloc(keysize);
/* Read the input data */
if(infile)
{
rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
if(rsa_inlen <= 0)
{
BIO_printf(bio_err, "Error reading input Data\n");
exit(1);
}
}
else
{
rsa_inlen=*inlen;
if(rsa_inlen <= 0 || rsa_inlen>keysize)
{
BIO_printf(bio_err, "Error reading input Data\n");
exit(1);
}
memmove(rsa_in,inbuf,rsa_inlen);
}
if(rev)
{
int i;
unsigned char ctmp;
for(i = 0; i < rsa_inlen/2; i++)
{
ctmp = rsa_in[i];
rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
rsa_in[rsa_inlen - 1 - i] = ctmp;
}
}
switch(rsa_mode)
{
case RSA_VERIFY:
rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
case RSA_SIGN:
rsa_outlen = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
case RSA_ENCRYPT:
rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
case RSA_DECRYPT:
rsa_outlen = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
}
if(rsa_outlen <= 0)
{
BIO_printf(bio_err, "RSA operation error\n");
ERR_print_errors(bio_err);
goto end;
}
ret = 0;
if(outfile)
{
if(asn1parse)
{
if(!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1))
{
ERR_print_errors(bio_err);
}
}
else if(hexdump) BIO_dump(out, (char *)rsa_out, rsa_outlen);
else BIO_write(out, rsa_out, rsa_outlen);
}
else
{
*outlen=rsa_outlen;
memmove(outbuf,rsa_out,rsa_outlen);
}
end:
RSA_free(rsa);
BIO_free(in);
BIO_free_all(out);
if(rsa_in) OPENSSL_free(rsa_in);
if(rsa_out) OPENSSL_free(rsa_out);
if(passin) OPENSSL_free(passin);
return ret;
}
#endif
int digest_func(char* in, unsigned int inlen, unsigned char* out, unsigned int* outlen)
{
EVP_MD_CTX mdctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
int md_len, i,ret;
//使EVP_Digest系列函数支持所有有效的信息摘要算法
OpenSSL_add_all_digests();
EVP_MD_CTX_init(&mdctx);
//使用md的算法结构设置mdctx结构,impl为NULL,即使用缺省实现的算法(open ssl本身提供的信息摘要算法)
ret = EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL);
if(ret <= 0)
{
return (-1);
}
//开始真正进行信息摘要运算,可以多次调用该函数,处理更多的数据,这里只调用了一次
ret = EVP_DigestUpdate(&mdctx, in, inlen);
if(ret <= 0)
{
return (-2);
}
//完成信息摘要计算过程,将完成的摘要信息存储在out里面,长度信息存储在*out_len里面
ret = EVP_DigestFinal_ex(&mdctx, out, outlen);
if(ret <= 0)
{
return (-3);
}
//使用该函数释放mdctx占用的资源,如果使用_ex系列函数,这是必须调用的。
EVP_MD_CTX_cleanup(&mdctx);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -