我想将 JWE JSON 转换为 PEM 格式。我正在使用 OpenSSL 和椭圆曲线密码术。
这是JSON
{"kty":"EC","crv":"P-256","x":"0FwHzpaCfb2Assd1LA3kX9_UssnhX_XuciyZ0sdDMpLuPNk","y":"gf67dENsd12GnxEvABuDoZVbVw4KQ5kD9sduH7bCWPVI8aE"}
现在根据crv
值,我正在设置 EC 曲线属性:
int eccgrp = OBJ_txt2nid('secp256k1');
int ecc_bits = 256;
int ecc_bytes = ecc_bits/8;
int ecc_digit_number = ecc_bytes/8;
EC_KEY *eccKey = EC_KEY_new_by_curve_name(eccgrp);
现在我将 JSON 解析为 JWK 对象
+ (NSString*) reverseEncoding:(NSString*)base64Url{
NSString *decodedString = nil;
decodedString = [base64Url stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
decodedString = [decodedString stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
return decodedString;
}
+ (NSString *) jwkToPem:(JWK*)jwk{
//NSString *kty = jwk->kty;
//NSString *crv= jwk->crv; // defaults to P-256
NSString *x= jwk->x; // base64url-encoded values
NSString *y= jwk->y; // base64url-encoded values
// Convert x, y components to Base64Url encoded format
NSString *base64X = [JOSESecurity reverseEncoding:x];
NSString *base64Y = [JOSESecurity reverseEncoding:y];
NSString *base64String = [NSString stringWithFormat:@"%@%@=", base64X,base64Y];
char * key = (char *)[base64String UTF8String];
NSString *pemFile = [self decodePublicKey:key];
return pemFile;
}
- (NSString*) decodePublicKey:(char*)hexJWKKey{
///** Computes r = generator * n + q * m
//* \param group underlying EC_GROUP object
//* \param r EC_POINT object for the result
//* \param n BIGNUM with the multiplier for the group generator (optional)
//* \param q EC_POINT object with the first factor of the second summand
//* \param m BIGNUM with the second factor of the second summand
//* \param ctx BN_CTX object (optional)
//* \return 1 on success and 0 if an error occured
//*/
//int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
//const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
EC_KEY *eckey = NULL;
EC_POINT *pub_key = NULL;
const EC_GROUP *group = NULL;
BIGNUM start;
BIGNUM *res;
BN_CTX *ctx;
BN_init(&start);
ctx = BN_CTX_new(); // ctx is an optional buffer to save time from allocating and deallocating memory whenever required
res = &start;
/*
BN_hex2bn() converts the string str containing a hexadecimal number to a BIGNUM and stores it in **bn.
If *bn is NULL, a new BIGNUM is created.
If bn is NULL, it only computes the number's length in hexadecimal digits.
If the string starts with '-', the number is negative.
BN_dec2bn() is the same using the decimal system.
*/
//BN_hex2bn(&res,"18E14A7B6A307F426SAMPLEHEXNUMBER35DB29A206321725");
BN_hex2bn(&res, hexJWKKey); // HERE hexJWKKey SEEMS TO BE WRONG
// Creates a new EC_KEY object using a named curve
eckey = EC_KEY_new_by_curve_name(eccgrp);
// Returns the EC_GROUP object of a EC_KEY object
group = EC_KEY_get0_group(eckey);
// Creates a new EC_POINT object for the specified EC_GROUP
pub_key = EC_POINT_new(group);
// Sets the private key of a EC_KEY object.
EC_KEY_set_private_key(eckey, res);
/* pub_key is a new uninitialized `EC_POINT*`. priv_key res is a `BIGNUM*`. */
if (!EC_POINT_mul(group, pub_key, res, NULL, NULL, ctx))
printf("Error at EC_POINT_mul.\n");
/** Sets the public key of a EC_KEY object.
* \param key EC_KEY object
* \param pub EC_POINT object with the public key (note: the EC_KEY object
* will use an own copy of the EC_POINT object).
*
*/
EC_KEY_set_public_key(eckey, pub_key);
/** Decodes a EC_POINT from a octet string
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param buf memory buffer with the encoded ec point
* \param len length of the encoded ec point
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occured
*/
/** the point is encoded as z||x||y, where z is the octet 0x04
POINT_CONVERSION_UNCOMPRESSED = 4,
*/
// char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, BN_CTX *);
char *client_public_key = EC_POINT_point2hex(group, pub_key, POINT_CONVERSION_UNCOMPRESSED, ctx);
//BN_CTX_free(client_public_key);
NSString *clientPublicKey = [NSString stringWithCString:client_public_key encoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:client_public_key length:clientPublicKey.length];
clientPublicKey = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
free(client_public_key);
return clientPublicKey;
}
因为当我们clientPublicKey
在下面的代码中使用时,thenkey
的结果是 nil。
EC_KEY *key = NULL;
BIO *in = NULL;
const char *cPem = NULL;
unsigned char *buffer = NULL;
BIGNUM start;
const BIGNUM *res;
BN_CTX *ctx;
BN_init(&start);
ctx = BN_CTX_new();
res = &start;
cPem = [clientPublicKey UTF8String];
in = BIO_new(BIO_s_mem());
BIO_puts(in, cPem);
key = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL);
// This key is nil.
key = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
// This key is also nil