Well, to roll out the possibility of network error's, JSON values not
being passed properly and blah blah blah I just dropped that approach.
instead of that I am running C program which prints the prime,generator and
public key. I have another program on same machine which is written in java
where I am hard coding these C generated values and trying to get the
public and secret key. ofcourse it is also giving me the same exception.
below is the complete C code written to generate DH params. most of the
part is taken from openSSL library source code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/dh.h>
#include <err.h>
static const char rnd_seed[] = "string to make the random number generator
think it has the entropy";
int main(){
BN_GENCB _cb;
DH *client= NULL;
char buf[12];
unsigned char *clientbuf=NULL;
int i,clientlen,clientout,ret=1;
BIO *out;
CRYPTO_malloc_debug_init();
CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
ERR_load_crypto_strings();
#ifdef OPENSSL_SYS_WIN32
CRYPTO_malloc_init();
#endif
RAND_seed(rnd_seed, sizeof rnd_seed);
out=BIO_new(BIO_s_file());
if (out == NULL) {
printf("BIO is null. exiting from program");
goto err;
}
BIO_set_fp(out,stdout,BIO_NOCLOSE);
//BN_GENCB_set(&_cb,&cb, out);//is this really required. my gcc not
recognizing cb instance so just commenting
client = DH_new();
if(client == NULL){
printf("Client DH is null");
goto err;
}
DH_generate_parameters_ex(client,1024,DH_GENERATOR_5,NULL);
if (!DH_check(client, &i)) {
goto err;
}
if (i & DH_CHECK_P_NOT_PRIME)
BIO_puts(out, "p value is not prime\n");
if (i & DH_CHECK_P_NOT_SAFE_PRIME)
BIO_puts(out, "p value is not a safe prime\n");
if (i & DH_UNABLE_TO_CHECK_GENERATOR)
BIO_puts(out, "unable to check the generator value\n");
if (i & DH_NOT_SUITABLE_GENERATOR)
BIO_puts(out, "the g value is not a generator\n");
BIO_puts(out,"\np=");//this prints the P in hex
printf("%s",BN_bn2dec(client->p));//this prints the P in decimal
BIO_puts(out,"\ng=");
BN_print(out,client->g);//prints generator which is 5 in this case
BIO_puts(out,"\n");
if (!DH_generate_key(client)) {
printf("unable to generate client keys");
goto err;
}
BIO_puts(out,"pri 1=");
BN_print(out,client->priv_key);//prints private key
BIO_puts(out,"\npub 1=");
printf("%s",BN_bn2dec(client->pub_key));//prints public key in
decimal format
DH *temp = DHparams_dup(client);
BIO_puts(out,"\n\n\n PEM = ");
PEM_write_bio_DHparams(out, temp);//this prints public key in base64
(this is what i think :) )
BIO_puts(out,"\n\n");
err:
if (clientbuf != NULL) OPENSSL_free(clientbuf);
if (serverbuf != NULL) OPENSSL_free(serverbuf);
if(server != NULL) DH_free(server);
if(client != NULL) DH_free(client);
BIO_free(out);
return 1;
}
This is what it prints when I ran this program.
p=106824077746282794452228647025839229808074839339760371103063155402464842614962676228255294325459053774613506891207056818441720848774298482866918174271328357364028843638451324415691330056638482781344307395975948664971732094293996189467599104442989563027727348339786810653279203313302815966250977426622843204103
g=5
pri1=622BBB2CA70FC8665F9EC3A95CF7B5C46D2F77AB10AA7D3FF485ADA9C6E005C7CF35AC0DBBFC256D2EB3AC702899140369433E1546B9DC915ACA5883D91F8FACB731F745B23C3A399FAFBDC6355E3D4203462432E950670297F6930B98C261A215053164893C2FAB55A1170699C3EDE919E59F895455B995A19C37670A6FA358
pub1=4373485839237796166699589228729451887524557806298817546317652313209684941935291316056752499275686842785989445002203537603465313281932431907074220666705812428468899520395399424699433568818334649395647035588736697462362131440308900155995886437558059484184376957451229991382889256903754886307405909744230582829
PEM = -----BEGIN DH PARAMETERS-----
MIGHAoGBAJgfXoi5POaY+aWtOFfykV7i9JNaX1ecr1W/PeqNwpcdTg1y75FaJwrO
LZSKds6dr6HtTEs5Jltda1GY2HklY8f3mja5EhNeLGLRfchQ8+Bn2FPGU1mMFpbF
07/tRJe6SOLfbQzIcTLn+TXbkS5fKWqerRnww4NZI0B+FBC+/DIHAgEF
-----END DH PARAMETERS-----
Here is my java code .
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import com.sun.crypto.provider.SunJCE;
public class DiffieHellmanServer {
private DiffieHellmanServer() {
};
public static void main(String argv[]) {
try {
DiffieHellmanServer keyAgree = new DiffieHellmanServer();
keyAgree.run1();
}
catch (Exception e) {
System.err.println("Error: " + e);
System.exit(1);
}
}
private void run1() throws Exception {
DHParameterSpec dhSkipParamSpec;
/** using C passed hard coded parameters*/
dhSkipParamSpec = new DHParameterSpec(skip1024Modulus,skip1024Base,
1024);
/*
Instead of base64,Even I tried with passing HEX and DECIMAL values
as a client public key and then converting them into byte[]. didn't work
*/
byte[] clientPubKeyEnc =new
sun.misc.BASE64Decoder().decodeBuffer("MIGHAoGBAJgfXoi5POaY+aWtOFfykV7i9JNaX1ecr1W/PeqNwpcdTg1y75FaJwrO"+
"LZSKds6dr6HtTEs5Jltda1GY2HklY8f3mja5EhNeLGLRfchQ8+Bn2FPGU1mMFpbF"+
"07/tRJe6SOLfbQzIcTLn+TXbkS5fKWqerRnww4NZI0B+FBC+/DIHAgEF");
KeyFactory bobKeyFac = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509KeySpec = new
X509EncodedKeySpec(clientPubKeyEnc);
PublicKey alicePubKey =
bobKeyFac.generatePublic(x509KeySpec); //*this throws
invalidKeySpecException : invalid key specification
*
/*
* Bob gets the DH parameters associated with Alice's public key. He
* must use the same parameters when he generates his own key pair.
*/
DHParameterSpec dhParamSpec = ((DHPublicKey)
alicePubKey).getParams();
/** Bob creates his own DH key pair */
KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
bobKpairGen.initialize(dhParamSpec);
KeyPair bobKpair = bobKpairGen.generateKeyPair();
/** Bob creates and initializes his DH KeyAgreement object */
KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
bobKeyAgree.init(bobKpair.getPrivate());
/** Bob encodes his public key, and sends it over to Alice. */
byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();
bobKeyAgree.doPhase(alicePubKey, true);
byte[] bobSharedSecret = bobKeyAgree.generateSecret();
/** print down Bob's shared key */
bobKeyAgree.doPhase(alicePubKey, true);
SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");
byte[] encodedKeybob = bobDesKey.getEncoded();
System.out.println(new BigInteger(encodedKeybob));
}
private static final BigInteger skip1024Modulus = new BigInteger(
"106824077746282794452228647025839229808074839339760371103063155402464842614962676228255294325459053774613506891207056818441720848774298482866918174271328357364028843638451324415691330056638482781344307395975948664971732094293996189467599104442989563027727348339786810653279203313302815966250977426622843204103");
/** The base used with the SKIP 1024 bit modulus */
private static final BigInteger skip1024Base = BigInteger.valueOf(5);
}
Regards,
Azhar
On Tue, Mar 19, 2013 at 4:53 PM, Matt Caswell <[email protected]> wrote:
> On 19 March 2013 10:37, azhar jodatti <[email protected]> wrote:
> >
> >
> > On Tue, Mar 19, 2013 at 2:58 PM, Matt Caswell <[email protected]> wrote:
> >>
> >> On 19 March 2013 09:01, azhar jodatti <[email protected]> wrote:
> >>
> >> > And possibly relevant here, the standard Suncle JCE provider actually
> >> > uses DSA paramgen for DH and thus imposes the DSA size restrictions
> >> > on DH -- 512 to 1024 in steps of 64 -- although they aren't required
> >> > by any standard I know of. I don't recall if JCE also restricts
> >> > *existing* (received) params; I'll test when I have some time.
> >> > I do recall you can get around this by using BouncyCastle instead.
> >> > But just using 1024 is easy and fine.
> >> > -->
> >> >
> >> > sometime I get below error "Prime size must be multiple of 64, and can
> >> > only range from 512 to 1024 (inclusive)"
> >> > when i use small prime numbers.It means JCE uses DSA paramateres for
> DH
> >> > algorithm. what is openSSL equalent to this?
> >> >
> >> > KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
> >> > kpg.initialize(1024);
> >> > keyPair = kpg.generateKeyPair();
> >> >
> >> > DHParameterSpec dhSpec = ((DHPublicKey)
> >> > keyPair.getPublic()).getParams();
> >> > baseGenerator = dhSpec.getG();
> >> > prime = dhSpec.getP();
> >> > sizeInBits = dhSpec.getL();
> >> > is this java code equalent to below c code?
> >> > DH_generate_parameters_ex(client,1024,DH_GENERATOR_5,NULL);
> >> >
> >> > see, with openSSL I have to pass DH_GENERATOR which only allowes (2
> and
> >> > 5) but that is not required in JAVA version.It generates it own base
> >> > generator.
> >>
> >> It appears to be equivalent, although I am not familiar with the JCE
> >> API. What I do not understand though is why you have code to generate
> >> parameters on *both* sides of your communication. If you are going to
> >> generate params every time (which both Dave and myself have advised
> >> against - it is an expensive operation), you still only need to do it
> >> on one side of the communication. So, after a bit of googling, I
> >> would expect to see something like this on the Java side (if the C
> >> side generates the params):
> >
> >
> > Well, above both the code snaps are at client side, not at server. I
> > understand I don't have to generate keys at both the end. I just wanted
> to
> > give you an idea how I am doing it in JAVA and C to generate the keys. As
> > you said both code appears to be equivalent but practically it won't
> seems
> > like . at-least in my scenario. because parameters generated with above
> java
> > code works with my server but that's not the case with parameters
> generated
> > with above C code.
> >
> >>
> >>
> >> KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
> >> kpg.initialize(new DHParameterSpec(/* p value passed from C */, /* g
> >> value passed from C */));
> >> keyPair = kpg.generateKeyPair();
> >>
> > yes, I m doing this at server. after generating keyPair I am generating
> > keyAgreent as well
> > . below is the code for this
> >
> > KeyAgreement keyAgree = KeyAgreement.getInstance("DH");
> > keyAgree.init(keyPair.getPrivate());
> > //this generates public key at server
> > byte[] serverPubKeyEnc = keyPair.getPublic().getEncoded();
> > //I really don't know how exactly it does this. but its mandatory
> > keyAgree.doPhase(clientPubllicKey, true);
> > //this generates secret key at server
> > byte[] sharedSecret = keyAgree.generateSecret();
> >
> Can you share the code where you load the parameters from the C into
> JCE? Also how you set up clientPublicKey. Finally would be useful if
> you can dump out the parameters after they have been read, and compare
> to the JSON sent.
>
> Matt
>