2014-03-03 3 views
0

타원 곡선 암호를 사용하려고합니다. Java에서 하나, C에서 두 가지 구현이 필요합니다. secp256k1 커브를 사용하여 생성 된 두 개의 키 쌍을 사용하여 테스트합니다. Java에서 파생 된 비밀을 생성 할 때마다 OpenSSL에서 얻은 것과 다른 수의 값을 얻습니다.BouncyCastle Java API 및 OpenSSL에 의해 생성 된 ECDH 비밀이 다릅니다.

자바 코드 :

/* privateKey and peerPublicKey are generated with the following parameters */ 
ECParameterSpec paramSpec = ECNamedCurveTable.getParameterSpec("secp256k1"); 
/* ... */ 
Provider BC = new BouncyCastleProvider(); 
KeyAgreement agr = KeyAgreement.getInstance("ECDH", BC); 
agr.init(privateKey); 
agr.doPhase(peerPublicKey, true); 
byte[] secret = agr.generateSecret(); 

C 코드

/* pkey and peerkey are generated using EC_KEY_new_by_curve_name(NID_secp256k1) */ 
/* and than wrapped in an EVP_PKEY */ 
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); 
uint8_t *secret = NULL; 
size_t secret_len; 
EVP_PKEY_derive_init(ctx); 
EVP_PKEY_derive_set_peer(ctx, peerkey); 
EVP_PKEY_derive(ctx, NULL, &secret_len); 
secret = malloc(secret_len); 
EVP_PKEY_derive(ctx, secret, &secret_len); 

내가 키가 유효하다는 것을 그들은 C와 자바 코드에서 모두 동일한 지 확인 해요,하지만 난 돈 ' 왜 파생 된 비밀이 다른지 이해하지 못합니다. 내가 놓친 게 있니?

감사

+0

"Java에서 파생 된 암호를 생성 할 때 나는 항상 OpenSSL에서 얻은 것과 다른 번호를 얻습니다." - 정확히 무엇을 의미하니? 프로토콜을 실행할 때마다 비밀이 달라 집니까? 아니면 OpenSSL 클라이언트와 BC 클라이언트 간의 프로토콜 실행이 공유 비밀에 도달하지 않는 경우입니까? – jww

답변

2
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); 
uint8_t *secret = NULL; 
size_t secret_len; 
EVP_PKEY_derive_init(ctx); 
EVP_PKEY_derive_set_peer(ctx, peerkey); 
EVP_PKEY_derive(ctx, NULL, &secret_len); 
secret = malloc(secret_len); 
EVP_PKEY_derive(ctx, secret, &secret_len); 

이 코드는 몇 가지 단계를없는 것 같습니다. 예를 들어 EVP_PKEY_paramgen_init이 없습니다.

OpenSSL 위키의 예는 Elliptic Curve Diffie-Hellman입니다. 링크 전용 답변을 피하기 위해 복사/붙여 넣기를하겠습니다. 그러나 Matt Caswell의 작업을 믿습니다.


EVP_PKEY_CTX *pctx, *kctx; 
EVP_PKEY_CTX *ctx; 
unsigned char *secret; 
EVP_PKEY *pkey = NULL, *peerkey, *params = NULL; 

/* Create the context for parameter generation */ 
if(NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) handleErrors(); 

/* Initialise the parameter generation */ 
if(1 != EVP_PKEY_paramgen_init(pctx)) handleErrors(); 

/* We're going to use the ANSI X9.62 Prime 256v1 curve */ 
if(1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1)) handleErrors(); 

/* Create the parameter object params */ 
if (!EVP_PKEY_paramgen(pctx, &params)) handleErrors(); 

/* Create the context for the key generation */ 
if(NULL == (kctx = EVP_PKEY_CTX_new(params, NULL))) handleErrors(); 

/* Generate the key */ 
if(1 != EVP_PKEY_keygen_init(kctx)) handleErrors(); 
if (1 != EVP_PKEY_keygen(kctx, &pkey)) handleErrors(); 

/* Get the peer's public key, and provide the peer with our public key - 
* how this is done will be specific to your circumstances */ 
peerkey = get_peerkey(pkey); 

/* Create the context for the shared secret derivation */ 
if(NULL == (ctx = EVP_PKEY_CTX_new(pkey, NULL))) handleErrors(); 

/* Initialise */ 
if(1 != EVP_PKEY_derive_init(ctx)) handleErrors(); 

/* Provide the peer public key */ 
if(1 != EVP_PKEY_derive_set_peer(ctx, peerkey)) handleErrors(); 

/* Determine buffer length for shared secret */ 
if(1 != EVP_PKEY_derive(ctx, NULL, secret_len)) handleErrors(); 

/* Create the buffer */ 
if(NULL == (secret = OPENSSL_malloc(*secret_len))) handleErrors(); 

/* Derive the shared secret */ 
if(1 != (EVP_PKEY_derive(ctx, secret, secret_len))) handleErrors(); 

EVP_PKEY_CTX_free(ctx); 
EVP_PKEY_free(peerkey); 
EVP_PKEY_free(pkey); 
EVP_PKEY_CTX_free(kctx); 
EVP_PKEY_free(params); 
EVP_PKEY_CTX_free(pctx); 

/* Never use a derived secret directly. Typically it is passed 
* through some hash function to produce a key */ 
return secret; 
나는 자바에서 파생 된 비밀을 생성 할 때 나는 항상 내가 OpenSSL을에서 무엇을 얻을에서 다른 번호를.

각 프로토콜 실행마다 다른 결과가 생성됩니다. 이는 각 당사자가 프로토콜 실행마다 임의의 값을 선택하기 때문입니다. 즉, g^aa은 임의로 실행될 때마다 다르므로 공개 키 A = g^a은 각 실행마다 다릅니다.

모든 것이 올바르게 작동하면 당사자가 동일한 값을 사용하거나 한 당사자가 과거 값을 다시 사용하지 않을 것입니다. 독립적 인 사형 집행은 결코 같은 결과를 가져 오지 않습니다. OpenSSL ↔ OpenSSL, OpenSSL ↔ Java 또는 Java ↔ Java가 중요합니다. 그들은 항상 다른 결과를 만들어 낼 것입니다.

관련 문제