static int convert_rsa_private_key(struct nettle_buffer *buffer, unsigned length, const uint8_t *data) { struct rsa_public_key pub; struct rsa_private_key priv; int res; rsa_public_key_init(&pub); rsa_private_key_init(&priv); if (rsa_keypair_from_der(&pub, &priv, 0, length, data)) { /* Reuses the buffer */ nettle_buffer_reset(buffer); res = rsa_keypair_to_sexp(buffer, NULL, &pub, &priv); } else { werror("Invalid PKCS#1 private key.\n"); res = 0; } rsa_public_key_clear(&pub); rsa_private_key_clear(&priv); return res; }
/* Returns 1 on success, 0 on error, and -1 for unsupported algorithms. */ static int convert_public_key(struct nettle_buffer *buffer, unsigned length, const uint8_t *data) { /* SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters OPTIONAL } */ struct asn1_der_iterator i; struct asn1_der_iterator j; int res = 0; if (asn1_der_iterator_first(&i, length, data) == ASN1_ITERATOR_CONSTRUCTED && i.type == ASN1_SEQUENCE && asn1_der_decode_constructed_last(&i) == ASN1_ITERATOR_CONSTRUCTED && i.type == ASN1_SEQUENCE /* Use the j iterator to parse the algorithm identifier */ && asn1_der_decode_constructed(&i, &j) == ASN1_ITERATOR_PRIMITIVE && j.type == ASN1_IDENTIFIER && asn1_der_iterator_next(&i) == ASN1_ITERATOR_PRIMITIVE && i.type == ASN1_BITSTRING /* Use i to parse the object wrapped in the bit string.*/ && asn1_der_decode_bitstring_last(&i)) { /* pkcs-1 { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) modules(0) pkcs-1(1) } -- -- When rsaEncryption is used in an AlgorithmIdentifier the -- parameters MUST be present and MUST be NULL. -- rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ static const uint8_t id_rsaEncryption[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; /* -- -- When dsa is used in an AlgorithmIdentifier the -- parameters MUST be present and MUST NOT be NULL. -- dsa OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 } */ static const uint8_t id_dsa[7] = { 0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01 }; switch (j.length) { unknown: default: werror("SubjectPublicKeyInfo: Unsupported algorithm.\n"); res = -1; break; case 7: if (memcmp(j.data, id_dsa, 7) == 0) { if (asn1_der_iterator_next(&j) == ASN1_ITERATOR_CONSTRUCTED && asn1_der_decode_constructed_last(&j) == ASN1_ITERATOR_PRIMITIVE) { struct dsa_public_key pub; dsa_public_key_init(&pub); if (dsa_params_from_der_iterator(&pub, 0, &i) && dsa_public_key_from_der_iterator(&pub, 0, &j)) { nettle_buffer_reset(buffer); res = dsa_keypair_to_sexp(buffer, NULL, &pub, NULL) > 0; } } if (!res) werror("SubjectPublicKeyInfo: Invalid DSA key.\n"); break; } else goto unknown; case 9: if (memcmp(j.data, id_rsaEncryption, 9) == 0) { if (asn1_der_iterator_next(&j) == ASN1_ITERATOR_PRIMITIVE && j.type == ASN1_NULL && j.length == 0 && asn1_der_iterator_next(&j) == ASN1_ITERATOR_END) { struct rsa_public_key pub; rsa_public_key_init(&pub); if (rsa_public_key_from_der_iterator(&pub, 0, &i)) { nettle_buffer_reset(buffer); res = rsa_keypair_to_sexp(buffer, NULL, &pub, NULL) > 0; } } if (!res) werror("SubjectPublicKeyInfo: Invalid RSA key.\n"); break; } else goto unknown; } } else werror("SubjectPublicKeyInfo: Invalid object.\n"); return res; }
int main(int argc, char **argv) { FILE *input = stdin; RSA *openssl_key = NULL; struct rsa_private_key *nettle_key = NULL; struct rsa_public_key *nettle_pub_key = NULL; struct nettle_buffer *sexp_buffer = NULL; OpenSSL_add_all_algorithms(); openssl_key = PEM_read_RSAPrivateKey(input, NULL, NULL, NULL); if(!openssl_key) { fprintf(stderr, "OpenSSL failed to read key: %s\n", ERR_error_string(ERR_get_error(), NULL)); return 1; } # ifdef DEBUG fprintf(stderr, "OpenSSL RSA private key:\n"); fprintf(stderr, "\tPrivate Exponent: %s\n", BN_bn2hex(openssl_key->d)); // d fprintf(stderr, "\tPrime 1: %s\n", BN_bn2hex(openssl_key->p)); // p fprintf(stderr, "\tPrime 2: %s\n", BN_bn2hex(openssl_key->q)); // q fprintf(stderr, "\tExponent 1: %s\n", BN_bn2hex(openssl_key->dmp1)); // a fprintf(stderr, "\tExponent 2: %s\n", BN_bn2hex(openssl_key->dmq1)); // b fprintf(stderr, "\tCoefficient: %s\n", BN_bn2hex(openssl_key->iqmp)); // c # endif nettle_key = (struct rsa_private_key*)malloc(sizeof(struct rsa_private_key)); if(!nettle_key) { fprintf(stderr, "Failed to malloc %zu bytes\n", sizeof(struct rsa_private_key)); return 4; } rsa_private_key_init(nettle_key); mpz_set_str(nettle_key->d, BN_bn2hex(openssl_key->d), 16); mpz_set_str(nettle_key->p, BN_bn2hex(openssl_key->p), 16); mpz_set_str(nettle_key->q, BN_bn2hex(openssl_key->q), 16); mpz_set_str(nettle_key->a, BN_bn2hex(openssl_key->dmp1), 16); mpz_set_str(nettle_key->b, BN_bn2hex(openssl_key->dmq1), 16); mpz_set_str(nettle_key->c, BN_bn2hex(openssl_key->iqmp), 16); if(rsa_private_key_prepare(nettle_key) != 1) { fprintf(stderr, "Nettle failed to prepare key\n"); return 2; } # ifdef DEBUG fprintf(stderr, "\tPrivate Exponent: %s\n", mpz_get_str(NULL, 16, nettle_key->d)); // d fprintf(stderr, "\tPrime 1: %s\n", mpz_get_str(NULL, 16, nettle_key->p)); // p fprintf(stderr, "\tPrime 2: %s\n", mpz_get_str(NULL, 16, nettle_key->q)); // q fprintf(stderr, "\tExponent 1: %s\n", mpz_get_str(NULL, 16, nettle_key->a)); // a fprintf(stderr, "\tExponent 2: %s\n", mpz_get_str(NULL, 16, nettle_key->b)); // b fprintf(stderr, "\tCoefficient: %s\n", mpz_get_str(NULL, 16, nettle_key->c)); // c # endif nettle_pub_key = (struct rsa_public_key*)malloc(sizeof(struct rsa_public_key)); if(!nettle_pub_key) { fprintf(stderr, "Failed to malloc %zu bytes\n", sizeof(struct rsa_public_key)); return 4; } rsa_public_key_init(nettle_pub_key); mpz_set_str(nettle_pub_key->n, BN_bn2hex(openssl_key->n), 16); mpz_set_str(nettle_pub_key->e, BN_bn2hex(openssl_key->e), 16); if(rsa_public_key_prepare(nettle_pub_key) != 1) { fprintf(stderr, "Nettle failed to prepare public key\n"); return 2; } sexp_buffer = (struct nettle_buffer*)malloc(sizeof(struct nettle_buffer)); if(!sexp_buffer) { fprintf(stderr, "Failed to malloc %zu bytes\n", sizeof(struct nettle_buffer)); return 4; } nettle_buffer_init(sexp_buffer); if(rsa_keypair_to_sexp(sexp_buffer, NULL, nettle_pub_key, nettle_key) == 0) { fprintf(stderr, "Nettle failed to export key to sexp\n"); return 3; } size_t bytes_written = fwrite(sexp_buffer->contents, 1, sexp_buffer->size, stdout); if(bytes_written < sexp_buffer->size) { fprintf(stderr, "Failed to write sexp to stdout\n"); return 5; } return 0; }
int test_main(void) { struct rsa_public_key pub; struct rsa_private_key priv; struct nettle_buffer buffer; rsa_public_key_init(&pub); rsa_private_key_init(&priv); mpz_set_str(pub.n, "085c3408989acae4faec3cbbad91c90d34c1d259cd74121a" "36f38b0b51424a9b2be514a04377113a6cdafe79dd7d5f2e" "cc8b5e9661189b86a7b22239907c25", 16); mpz_set_str(pub.e, "36ad4b1d", 16); ASSERT(rsa_public_key_prepare(&pub)); mpz_set_str(priv.d, "06ee6d4ff3c239e408150daf8117abfa36a40ad4455d9059" "a86d52f33a2de07418a0a699594588c64810248c9412d554" "f74af947c73c32007e87c92f0937ed", 16); mpz_set_str(priv.p, "03259879b24315e9cf14254824c7935d807cdb6990f414a0" "f65e6065130a611f", 16); mpz_set_str(priv.q, "02a81ba73bad45fc73b36deffce52d1b73e0747f4d8a8264" "8cecd310448ea63b", 16); mpz_set_str(priv.a, "026cbdad5dd0046e093f060ecd5b4ac918e098b0278bb752" "b7cadd6a8944f0b9", 16); mpz_set_str(priv.b, "0148751e622d6d58e3bb094afd6edacf7370351d068e2ce9" "f565c5528c4a7473", 16); mpz_set_str(priv.c, "f8a458ea73a018dc6fa56863e3bc6de405f364f77dee6f09" "62679ea1a8282e", 16); ASSERT(rsa_private_key_prepare(&priv)); nettle_buffer_init(&buffer); ASSERT(rsa_keypair_to_sexp(&buffer, "rsa", &pub, &priv)); if (verbose) { printf("private:"); print_hex(buffer.size, buffer.contents); } ASSERT(MEMEQH(buffer.size, buffer.contents, "2831313a707269766174652d6b657928" "333a72736128313a6e36333a085c3408" "989acae4faec3cbbad91c90d34c1d259" "cd74121a36f38b0b51424a9b2be514a0" "4377113a6cdafe79dd7d5f2ecc8b5e96" "61189b86a7b22239907c252928313a65" "343a36ad4b1d2928313a6436333a06ee" "6d4ff3c239e408150daf8117abfa36a4" "0ad4455d9059a86d52f33a2de07418a0" "a699594588c64810248c9412d554f74a" "f947c73c32007e87c92f0937ed292831" "3a7033323a03259879b24315e9cf1425" "4824c7935d807cdb6990f414a0f65e60" "65130a611f2928313a7133323a02a81b" "a73bad45fc73b36deffce52d1b73e074" "7f4d8a82648cecd310448ea63b292831" "3a6133323a026cbdad5dd0046e093f06" "0ecd5b4ac918e098b0278bb752b7cadd" "6a8944f0b92928313a6233323a014875" "1e622d6d58e3bb094afd6edacf737035" "1d068e2ce9f565c5528c4a7473292831" "3a6333323a00f8a458ea73a018dc6fa5" "6863e3bc6de405f364f77dee6f096267" "9ea1a8282e292929")); nettle_buffer_clear(&buffer); ASSERT(rsa_keypair_to_sexp(&buffer, NULL, &pub, NULL)); if (verbose) { printf("public:"); print_hex(buffer.size, buffer.contents); } ASSERT(MEMEQH(buffer.size, buffer.contents, "2831303a7075626c69632d6b65792839" "3a7273612d706b63733128313a6e3633" "3a085c3408989acae4faec3cbbad91c9" "0d34c1d259cd74121a36f38b0b51424a" "9b2be514a04377113a6cdafe79dd7d5f" "2ecc8b5e9661189b86a7b22239907c25" "2928313a65343a36ad4b1d292929")); rsa_public_key_clear(&pub); rsa_private_key_clear(&priv); SUCCESS(); }