支持任意长度RSA密钥分段加解密、签名与验签的c版本实现
实现及测试代码:rsatest.c
#include <stdio.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include "sha1.h"
static char base64_digits[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
long str_Encode64(long in_lIn, const char* in_pszIn, char* out_pszOut)
{
register i;
unsigned char *p;
if(!in_pszIn)
{
printf("base64编码时输入数据为空\n");
return -1;
}
p = (unsigned char*)in_pszIn;
for(i = 0; in_lIn >= 3; in_lIn -= 3, p += 3)
{
out_pszOut[i++] = base64_digits[p[0] >> 2];
out_pszOut[i++] = base64_digits[(p[0] << 4 & 0x30) | p[1] >> 4];
out_pszOut[i++] = base64_digits[(p[1] << 2 & 0x3C) | p[2] >> 6];
out_pszOut[i++] = base64_digits[p[2] & 0x3F];
}
switch(in_lIn)
{
case 1:
out_pszOut[i++] = base64_digits[p[0] >> 2];
out_pszOut[i++] = base64_digits[p[0] << 4 & 0x30];
out_pszOut[i++] = '=';
out_pszOut[i++] = '=';
break;
case 2:
out_pszOut[i++] = base64_digits[p[0] >> 2];
out_pszOut[i++] = base64_digits[p[0] << 4 & 0x30 | p[1] >> 4];
out_pszOut[i++] = base64_digits[p[1] << 2 & 0x3C];
out_pszOut[i++] = '=';
break;
case 0:
default:
break;
}
out_pszOut[i] = 0;
return 0;
}
long str_Decode64(const char* in_pszIn, int* out_plOut, char* out_pszOut)
{
register i, k = 0, n;
unsigned char t, c, *p;
if(!in_pszIn)
{
printf("输入需解码的字符串为空!\n");
return -1;
}
n = strlen(in_pszIn);
p = (unsigned char*)in_pszIn;
for(i = 0; i < n; i++)
{
if('=' == *p)
break;
do
{
if(*p)
{
c = *p;
if('A' <= c && 'Z'>= c)
c -= 'A';
else if( 'a' <= c && 'z' >= c)
c = c - 'a' + 26;
else if( '0' <= c && '9' >= c)
c = c - '0' + 52;
else if( '+' == c)
c = 62;
else if( '/' == c)
c = 63;
else
c = 64; /* 无效字符 */
}
else
c = 65; /* 字符串结束符*/
p++;
}while(64 == c); /* 跳过无效字符*/
if( 65 == c) break;
switch(i % 4)
{
case 0:
t = c << 2;
break;
case 1:
out_pszOut[k++] = (unsigned char)( t | c >> 4);
t = (unsigned char)(c << 4);
break;
case 2:
out_pszOut[k++] = (unsigned char)(t | c >> 2);
t = (unsigned char)(c << 6);
break;
case 3:
out_pszOut[k++] = (unsigned char)(t | c);
break;
}
}
*out_plOut = k;
return 0;
}
int rsa_enc(char *publickey,char *message,char **cipher)
{
FILE *fp = NULL;
RSA *publicRsa = NULL;
*cipher = NULL;
if ((fp = fopen(publickey, "r")) == NULL)
{
printf("public key path error\n");
return -1;
}
if ((publicRsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL)) == NULL)
{
printf("PEM_read_RSA_PUBKEY error\n");
fclose(fp);
return -1;
}
fclose(fp);
//RSA单次运算长度,由密钥长度决定
int rsaLen = RSA_size(publicRsa);
//单次运算输入长度,由填充方式决定
//RSA_PKCS1_PADDING 固定填充11位
int blockLen = rsaLen-11;
//单次运算的加密结果,固定长度为rsaLen
char *encrypt = (char *)malloc(rsaLen);
if(encrypt==NULL)
{
printf("encrypt malloc error\n");
RSA_free(publicRsa);
return -1;
}
//加密后的完整密文
int msgLen = strlen(message);
int encLen = (msgLen/blockLen+1)*rsaLen; //rsaLen的整数倍
char *encMessage = (char *)malloc(encLen);
if(encMessage==NULL)
{
printf("encMessage malloc error\n");
RSA_free(publicRsa);
free(encrypt);
encrypt=NULL;
return -1;
}
memset(encMessage,0x0,encLen);
int ret,index,index1;
for(index=0,index1=0;index<=msgLen;index=index+blockLen,index1++)
{
//加密
memset(encrypt,0x0,rsaLen);
if((index+blockLen)>msgLen)
ret = RSA_public_encrypt(msgLen-index, message+index, encrypt, publicRsa, RSA_PKCS1_PADDING);
else
ret = RSA_public_encrypt(blockLen, message+index, encrypt, publicRsa, RSA_PKCS1_PADDING);
if (ret < 0)
{
printf("RSA_public_encrypt error\n");
RSA_free(publicRsa);
free(encrypt);
encrypt=NULL;
free(encMessage);
encMessage=NULL;
return -1;
}
memcpy(encMessage+index1*rsaLen,encrypt,rsaLen);
}
//提前释放过程变量
RSA_free(publicRsa);
free(encrypt);
encrypt=NULL;
//base64的长度为向上取3的整数倍后除3乘4 (x+2)/3*4+1
int base64Len = (encLen+2)/3*4+1;
*cipher = (char *)malloc(base64Len);
if(*cipher==NULL)
{
printf("cipher malloc error\n");
free(encMessage);
encMessage=NULL;
return -1;
}
memset(*cipher,0x0,base64Len);
//base64
ret = str_Encode64(encLen, encMessage, *cipher);
free(encMessage);
encMessage=NULL;
if(ret<0)
{
printf("Encode64 error\n");
free(*cipher);
*cipher=NULL;
return -1;
}
return 0;
}
int rsa_dec(char *privateKey,char *cipher,char **message)
{
FILE *fp = NULL;
RSA *privateRsa = NULL;
*message = NULL;
if ((fp = fopen(privateKey, "r")) == NULL)
{
printf("private key path error\n");
return -1;
}
if ((privateRsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL)
{
printf("PEM_read_RSAPrivateKey error\n");
fclose(fp);
return -1;
}
fclose(fp);
//base64解码长度为除4乘3
int encLen = strlen(cipher)/4*3;
char *encMessage = (char *)malloc(encLen);
if(encMessage==NULL)
{
printf("encMessage malloc error\n");
RSA_free(privateRsa);
return -1;
}
memset(encMessage,0x0,encLen);
//base64 解码
encLen = 0;
int ret = str_Decode64(cipher,&encLen,encMessage);
if(ret<0)
{
printf("Decode64 error\n");
RSA_free(privateRsa);
free(encMessage);
encMessage=NULL;
return -1;
}
//RSA单次运算长度,由密钥长度决定
int rsaLen = RSA_size(privateRsa);
//单次运算的解密结果,长度不会超过rsaLen
char *plain = (char *)malloc(rsaLen);
if(plain==NULL)
{
printf("plain malloc error\n");
RSA_free(privateRsa);
free(encMessage);
encMessage=NULL;
return -1;
}
//明文
int msgLen = encLen + 1;
*message = (char *)malloc(msgLen);
if(*message==NULL)
{
printf("cipher malloc error\n");
RSA_free(privateRsa);
free(encMessage);
encMessage=NULL;
free(plain);
plain=NULL;
return -1;
}
memset(*message,0x0,msgLen);
int index,decLen,offset=0;
for(index=0;index<encLen;index=index+rsaLen)
{
//解密
memset(plain,0x0,rsaLen);
if((index+rsaLen)>encLen)
decLen = RSA_private_decrypt(encLen-index, encMessage+index, plain, privateRsa, RSA_PKCS1_PADDING);
else
decLen = RSA_private_decrypt(rsaLen, encMessage+index, plain, privateRsa, RSA_PKCS1_PADDING);
if ( encLen < 0)
{
printf("RSA_private_decrypt error\n");
RSA_free(privateRsa);
free(encMessage);
encMessage=NULL;
free(plain);
plain=NULL;
free(*message);
*message=NULL;
return -1;
}
memcpy(*message+offset,plain,decLen);
offset = offset+decLen;
}
//释放过程变量
free(encMessage);
encMessage=NULL;
free(plain);
plain=NULL;
RSA_free(privateRsa);
return 0;
}
int rsa_sign(char *privateKey,char *cipher,char **sign)
{
FILE *fp = NULL;
RSA *privateRsa = NULL;
*sign = NULL;
if ((fp = fopen(privateKey, "r")) == NULL)
{
printf("private key path error\n");
return -1;
}
if ((privateRsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL)
{
printf("PEM_read_RSAPrivateKey error\n");
fclose(fp);
return -1;
}
fclose(fp);
//RSA单次运算长度,由密钥长度决定
int rsaLen = RSA_size(privateRsa);
//签名长度,固定为rsaLen
char *rsaSign = (char *)malloc(rsaLen);
if(rsaSign==NULL)
{
printf("rsaSign malloc error\n");
RSA_free(privateRsa);
return -1;
}
memset(rsaSign,0x0,rsaLen);
int signLen = (rsaLen+2)/3*4+1;
*sign = (char *)malloc(signLen);
if(*sign==NULL)
{
printf("sign malloc error\n");
RSA_free(privateRsa);
free(rsaSign);
rsaSign=NULL;
return -1;
}
memset(*sign,0x0,signLen);
//sha1运算
char sha1sum[20];
memset(sha1sum,0x0,sizeof(sha1sum));
sha1_csum(cipher, strlen(cipher), sha1sum);
//使用私钥对SHA1摘要做签名
int ret = RSA_sign(NID_sha1, sha1sum, sizeof(sha1sum), rsaSign, &signLen, privateRsa);
if(ret != 1 )
{
printf("rsa sign error\n");
RSA_free(privateRsa);
free(rsaSign);
rsaSign=NULL;
free(*sign);
*sign=NULL;
return -1;
}
//base64
ret = str_Encode64(signLen, rsaSign, *sign);
free(rsaSign);
rsaSign=NULL;
if(ret<0)
{
printf("Encode64 error\n");
RSA_free(privateRsa);
free(*sign);
*sign=NULL;
return -1;
}
RSA_free(privateRsa);
return 0;
}
int rsa_verify(char *publickey,char *cipher,char *sign)
{
FILE *fp = NULL;
RSA *publicRsa = NULL;
if ((fp = fopen(publickey, "r")) == NULL)
{
printf("public key path error\n");
return -1;
}
if ((publicRsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL)) == NULL)
{
printf("PEM_read_RSA_PUBKEY error\n");
fclose(fp);
return -1;
}
fclose(fp);
//RSA单次运算长度,由密钥长度决定
int rsaLen = RSA_size(publicRsa);
//签名长度,固定为rsaLen
char *rsaSign = (char *)malloc(rsaLen);
if(rsaSign==NULL)
{
printf("rsaSign malloc error\n");
RSA_free(publicRsa);
return -1;
}
memset(rsaSign,0x0,rsaLen);
//base64 解码
int signlen = 0;
int ret = str_Decode64(sign,&signlen,rsaSign);
if(ret<0)
{
printf("Decode64 error\n");
RSA_free(publicRsa);
free(rsaSign);
rsaSign=NULL;
return -1;
}
//sha1运算
char sha1sum[20];
memset(sha1sum,0x0,sizeof(sha1sum));
sha1_csum(cipher, strlen(cipher), sha1sum);
//验签
ret = RSA_verify(NID_sha1, sha1sum, sizeof(sha1sum), rsaSign, signlen, publicRsa);
free(rsaSign);
rsaSign=NULL;
if(ret != 1 )
{
printf("rsa verify error\n");
RSA_free(publicRsa);
return -1;
}
RSA_free(publicRsa);
return 0;
}
int main(int argc, char *argv[])
{
int ret;
char *message;
if(argc==2)
message = argv[1];
else
{
printf("usage: %s message\n",argv[0]);
return -1;
}
printf("加密前message=[%s]\n",message);
//加密
char *cipher;
ret = rsa_enc("rsa_key",message,&cipher);
if(ret<0) return ret;
printf("密文base64=[%s]\n",cipher);
//解密
char *message1;
ret = rsa_dec("rsa_privateKey",cipher,&message1);
if(ret<0)
{
free(cipher);
cipher=NULL;
return ret;
}
printf("解密后message=[%s]\n",message1);
if(memcmp(message,message1,strlen(message))!=0)
{
printf("解密值对比失败\n");
return ret;
}
//签名
char *sign;
ret = rsa_sign("rsa_privateKey",cipher,&sign);
if(ret<0)
{
free(cipher);
cipher=NULL;
free(message1);
message1=NULL;
return ret;
}
printf("签名base64=[%s]\n",sign);
//验签
ret = rsa_verify("rsa_key",cipher,sign);
if(ret==0) printf("签名值验证成功\n");
free(cipher);
cipher=NULL;
free(message1);
message1=NULL;
free(sign);
sign=NULL;
return ret;
}
sha1实现代码:sha1.c
#include "sha1.h"
void sha1_starts( sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void sha1_process( sha1_context *ctx, unsigned char data[64] )
{
unsigned long temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[0], data, 0 );
GET_UINT32_BE( W[1], data, 4 );
GET_UINT32_BE( W[2], data, 8 );
GET_UINT32_BE( W[3], data, 12 );
GET_UINT32_BE( W[4], data, 16 );
GET_UINT32_BE( W[5], data, 20 );
GET_UINT32_BE( W[6], data, 24 );
GET_UINT32_BE( W[7], data, 28 );
GET_UINT32_BE( W[8], data, 32 );
GET_UINT32_BE( W[9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
void sha1_update( sha1_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
void sha1_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha1_update( ctx, (unsigned char *) sha1_padding, padn );
sha1_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
}
void sha1_csum( unsigned char *input, int ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
}
sha1头文件:sha1.h
#if !defined(wp_SHA1_H)
#define wp_SHA1_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
// SHA1.h : header file
//
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
typedef struct
{
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
}sha1_context;
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
void sha1_starts( sha1_context *ctx );
void sha1_process( sha1_context *ctx, unsigned char data[64] );
void sha1_update( sha1_context *ctx, unsigned char *input, int ilen );
void sha1_finish( sha1_context *ctx, unsigned char output[20] );
void sha1_csum( unsigned char *input, int ilen, unsigned char output[20] );
#endif // !defined(wp_SHA1_H)
编译文件:makefile
CC=gcc -g -I$(HOME)/include -L$(HOME)/lib -lssl -lz
all: rsatest
rsatest: rsatest.c sha1.c
$(CC) $+ -o $@
clean:
rm rsatest
测试用到的私钥:rsa_privateKey
-----BEGIN PRIVATE KEY-----
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
pZnrv4o0EbpPvXS14gcXyoEz0fmlbA==
-----END PRIVATE KEY-----
测试用到的公钥:rsa_key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuqrysY82fV3MxJG1eJ6A
mS9ms28bMt2E8vYaygXmDnDi8Cq5LmU/EjJ5F4gkl/05O5BaMc4D4x81IgkK56Cu
Ew5QTlpLgBJR5w/IUbwz4o40/fi0vmw5+fD6i/maYn8JJhwt9GFLkPvKY/0bi+Mm
ELxf9Lvf7+3kFMF9qbWi9B9BennkeJGVE3VlgpK7FPmRNvF4N8rM+l3snG9QV9er
+1n6gud5XU4cDjB+cyWWJEijxkxtQDAnxa4D1bZgmyZP8Y5fOVvDzPxBdFId2qnm
M7c7B89r1aMDTjtZ/UHndNEEuWpzo7rCveH5m5d2OLZPXaiomiXDsAS8mBF4tBuZ
O5ocAvET0ek0WOnMA2RniFdnKFWmk48qPgLQBoWyLW1uGw2ApoO5XMJ3IUoFhoYn
h6zvBBkLUM4gPTLUvDZWm0nd5TCPYMfuoO/bWo8xhLzfBDDx4hcKJA9bR260RpmG
+LVqkaJ34cShppu400Oh80+HtIrvniG9PeQlv/PNcxhTehQrSxlfkv/O7yE4+H10
Z9J8OXD4nFmFzuIrh9rNbCP8TczqoEthE08SGAt70e6BIlZWCQoJHUoy3twwFOZ9
/YoYZ8oQEHr1YET5AHFe735ECrVYvNPNGYjHuv80dcL4J6YCRsjoC+jTjbR4ifHW
1LxvxYDecWs5s2D8AhtxB8cCAwEAAQ==
-----END PUBLIC KEY-----