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 <dthomp...@prinpay.com> wrote: > > From: owner-openssl-us...@openssl.org 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 openssl-users@openssl.org > Automated List Manager majord...@openssl.org >