2

我想将 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
4

0 回答 0