Hi Dave,
Thanks a lot for your detailed explanation. GT.M supports ASCII format also.
i believe converting base64 is better way instead of ASCII.
I had changed as per your suggestion and code worked for me. additionally i
had tested the Decode also, now everything is fine. can you please verify
the decoded pubkey and d2i_RSA_PUBKEY implemented correctly here.
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
int main(int argc, char* argv[]) {
/* Variables */
unsigned char bfbuf[2000];
unsigned char buf[2000];
unsigned char b64buf[3000];
unsigned char *next,*next1;
RSA *key,*pub_key;
FILE *fp;
int outlen,status;
int len,len1, total = 0;
int total1=0;
long length;
/* EVP_Encode*() Base64 */
EVP_ENCODE_CTX ectx;
next=buf;
printf("generating key...\n");
fp=fopen("public.pem","r");
key =(RSA *)PEM_read_RSA_PUBKEY(fp,NULL,NULL,NULL);
printf("RSA size for key=%d\n",RSA_size(key));
//len=i2d_RSAPublicKey(key, &next);
len=i2d_RSA_PUBKEY(key, &next);
fclose(fp);
printf("DER character buffer length=%d",len);
/* Base64 using EVP */
printf("\nEncoding RSA string...");
EVP_EncodeInit(&ectx);
EVP_EncodeUpdate(&ectx, b64buf, &outlen, buf, len);
total += outlen;
EVP_EncodeFinal(&ectx, b64buf + outlen, &len);
total += outlen;
printf("\nBase64 encoded length string: %d,%d\n",total,len);
printf("\nBase64 encoded string: %s\n",b64buf);
/* Base64 decodification */
printf("\nDecoding string...");
EVP_DecodeInit(&ectx);
EVP_DecodeUpdate(&ectx, bfbuf, &len1, b64buf, strlen(b64buf));
total1 +=len1;
EVP_DecodeFinal(&ectx, bfbuf + len1, &len1);
total1 +=len1;
printf("\nBase64 decoded length string: %d,%d\n",total1,len1);
<--------- here len1 is 0, why len1 is zero here is it right?
printf("\nBase64 decoded string:
%s\n",bfbuf); <------------------- i
understood this will not print
next1=bfbuf;
length=total1;
pub_key=d2i_RSA_PUBKEY(NULL,(const unsigned char**)&next1, total1);
printf("RSA size for pub_key=%d\n",RSA_size(pub_key));
return 1;
}
kicha@kicha-laptop:~/openssl$
outcome:
-------------
RSA size for key=128
DER character buffer length=162
Encoding RSA string...
Base64 encoded length string: 390,25
Base64 encoded string:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9TI3eLAsOolBjnrrhGEAI7fiy
nnCgn0tzSSNEGNeMOvPcxlwXiTqt2iYZ39LoXJPRfFC6tPIDomcr1ijBXT07Tr2P
mjGq3BDS8a9CNQhIm0m3nIhkP3+hCXbvLYqfuim87voeXgjycD4aVVlqCca82SzI
fVKneZGtvJ7wtxv/uQIDAQAB
Decoding string...
Base64 decoded length string: 162,0 <------------------how this value
will be 0.
e64 e*�H�ed string: 0��0
RSA size for pub_key=128
Thanks for your time,
Krishnamurthy
On Tue, Aug 9, 2011 at 2:47 AM, Dave Thompson <[email protected]> wrote:
> > From: [email protected] On Behalf Of krishnamurthy
> santhanam
> > Sent: Saturday, 06 August, 2011 15:13
>
> > Thanks for your suggestion. Let me explain in what i am doing.
> > I have GT.M(MUMPS) calls to C language(external calls) routines that
> > has to generate RSA key pairs and send it to the GT.M(same server).
>
> > DO &security.rsakey(char *pubkey,char *privatekey)
>
> > GT.M stores the key pairs in database and shares the public key
> only.
> > GTM will accept only strings and characters. hence i had tried to
> > i2d/d2i methods to right the keys to database.
>
> *If* those are C strings, DER by itself cannot be a C string.
> Interlanguage calls sometimes use other kinds of strings, some of
> which can handle binary data. I'll assume a C string. There are
> several ways of encoding DER (or other binary data) to make it
> a printable string and easily manipulable in C and other tools
> designed for printable strings; I'll assume that includes GT.M.
>
> You'll need to use whatever method GT.M requires (or allows).
> PEM and base64, the two you have (nearly) coded, are two related
> and popular ways, but not the only ways. Do you know this is
> what GT.M wants?
>
> > I had tried below program but it is giving error. i had
> > created RSA keys and the tried to extract the public key
> > using i2d_RSApublickey then tried to encode the keys using
> > EVP_Encodeinit()...Am i doing wrong? any help would be great
>
> See below. (So far you're only trying to encode one key, the
> publickey; from your description you will also need to do
> the privatekey, but one step at a time.)
>
> <code trimmed>
> > unsigned char *next;
> > RSA *key;
> > int outlen,status,len, total = 0;
> > /* EVP_Encode*() Base64 */
> > EVP_ENCODE_CTX ectx;
> > EVP_CIPHER_CTX ctx;
> > EVP_PKEY *pkey;
> > pkey = EVP_PKEY_new();
> > next=buf;
> > printf("generating key...\n");
> > key = RSA_generate_key(1024,RSA_F4, NULL, NULL);
>
> As I said before, check for failure (null) before using.
>
> > EVP_PKEY_assign_RSA(pkey,key);
> > if (RSA_check_key(key)==1)
>
> This is redundant: if RSA_generate_key succeeded, the key is good.
> RSA_check_key is useful where you get a keypair from somewhere else,
> like storage or a comm partner, who might have screwed it up
> (either accidentally, or an adversary deliberately interfering).
>
> > {
> > fp=fopen("public.pem","w"); <snip>
> > PEM_write_PUBKEY(fp,pkey);
> > fclose(fp);
> > len=i2d_RSAPublicKey(key, &next);
> > printf("length=%d",len); <snip>len=140
> > }
>
> There are both subtle and obvious differences here.
> PEM_write_PUBKEY encodes the pubkey part in a generic
> DER format defined by X.509 called SubjectPublicKeyInfo,
> then encodes to PEM (which is base64 + fold + labels).
> i2d_RSAPublicKey() encodes to *PKCS1* DER format, which
> is slightly different. If you want (that is, GT.M wants)
> KeyInfo DER, instead use i2d_RSA_PUBKEY or just i2d_PUBKEY.
>
> > /* Base64 using EVP */
> > printf("\nEncoding RSA string...");
> > EVP_EncodeInit(&ectx);
> > EVP_EncodeUpdate(&ectx, b64buf, &len, buf, outlen);
> > total += len;
>
> Here's your immediate error. You have the DER in buf for len,
> so 'inl' should be len, and 'outl' should be &outlen and then
> you add outlen to total. (Actually here you know total is 0
> so you can just assign instead, but add is more general.)
>
> > EVP_EncodeFinal(&ectx, b64buf + len, &len);
> > total += len;
>
> Similarly these should be outlen. Actually b64buf+len could be
> either b64buf+outlen (from prev call) or b64buf+total; they're
> actually the same here but the latter is more logical.
>
> > printf("\nBase64 encoded length string: %d,%d\n",total,len);
> > ----------------->outcome is 0,0
> > printf("\nBase64 encoded string: %s\n",b64buf);
> > --------------------------------> see the below outcome
> > EVP_CIPHER_CTX_cleanup(&ctx);
>
> You didn't init ctx (or use it at all), so it's not safe
> to clean it, and in fact you got a glibc fault (snipped).
>
> You certainly don't want to encrypt your publickey;
> publickeys are public. Whether, and how, you want to
> encrypt your privatekey depends on what GT.M wants.
> If he's storing it in a database, it may reasonably
> depend on what control he has over that database.
>
> For clear RSA privatekey there is one DER standard (PKCS1)
> which i2d_RSAPrivateKey implements. But for encrypted
> there are several standards, which differ both on the
> encoding and the encryption, plus proprietary schemes.
>
>
>
> ______________________________________________________________________
> OpenSSL Project http://www.openssl.org
> User Support Mailing List [email protected]
> Automated List Manager [email protected]
>