Codebase list libcryptx-perl / 9bc7116
Add ability to export ecc keys in short/oid form. (#17) * Add PK_CURVEOID flag to ecc_export_full The flag exports the key with it's associated ASN.1 OID which itself references the curves parameters. This is like OPENSSL_EC_NAMED_CURVE in OpenSSL. * Add ecc_dp_fill_from_sets to look up missing curve parameters Exporting with PK_CURVEOID requires knowing the OID, however only some key formats provide the OID. ecc_dp_fill_from_sets searches our known set of curves and fills in the missing parameters like curve OID and name. Additional we can now make the name parameter in ecc_dp_set optional. * Add optional OID parameter to ecc_dp_set * Add support for PK_CURVEOID to perl-CryptX API: $pk->export_key_der('private_short'); $pk->export_key_der('public_short'); $pk->export_key_pem('private_short'); $pk->export_key_pem('public_short'); * Make key2hash export the OID as curve_oid Manuel Mausz authored 7 years ago karel-m committed 7 years ago
13 changed file(s) with 243 addition(s) and 77 deletion(s). Raw diff Collapse all Expand all
185185 {
186186 HV *h;
187187 SV *param, **pref;
188 SV **sv_cofactor, **sv_prime, **sv_A, **sv_B, **sv_order, **sv_Gx, **sv_Gy;
188 SV **sv_cofactor, **sv_prime, **sv_A, **sv_B, **sv_order, **sv_Gx, **sv_Gy, **sv_oid;
189189 int err;
190190 char *ch_name;
191191 STRLEN l_name;
199199 }
200200 else if (SvROK(curve)) {
201201 param = curve;
202 ch_name = "custom";
203202 }
204203 else {
205204 croak("FATAL: curve has to be a string or a hashref");
231230 SvPV_nolen(*sv_Gx),
232231 SvPV_nolen(*sv_Gy),
233232 (unsigned long)SvUV(*sv_cofactor),
234 ch_name );
233 NULL, /* we intentionally don't allow setting custom names */
234 NULL /* we intentionally don't allow setting custom OIDs */
235 );
235236 return err == CRYPT_OK ? dp : NULL;
236237 }
237238
427428
428429 INCLUDE: inc/CryptX_KeyDerivation.xs.inc
429430
430 INCLUDE: inc/CryptX_BigInt_LTM.xs.inc
431 INCLUDE: inc/CryptX_BigInt_LTM.xs.inc
168168 name = newSVpv(self->key.dp->name, strlen(self->key.dp->name));
169169 name_ptr = SvPV(name, name_len);
170170 for (i=0; i<name_len && name_ptr[i]>0; i++) name_ptr[i] = toLOWER(name_ptr[i]);
171 not_used = hv_store(rv_hash, "curve_name", 10, name, 0);
171 not_used = hv_store(rv_hash, "curve_name", 10, name, 0);
172 }
173 if (self->key.dp->oid.OIDlen > 0) {
174 int i;
175 SV *oid = newSVpv("", 0);
176 for(i = 0; i < self->key.dp->oid.OIDlen - 1; i++) sv_catpvf(oid, "%lu.", self->key.dp->oid.OID[i]);
177 sv_catpvf(oid, "%lu", self->key.dp->oid.OID[i]);
178 not_used = hv_store(rv_hash, "curve_oid", 9, oid, 0);
172179 }
173180 }
174181 /* =====> size */
189196 unsigned long int out_len = 4096;
190197
191198 RETVAL = newSVpvn(NULL, 0); /* undef */
192 if (strnEQ(type, "private", 7)) {
199 if (strnEQ(type, "private_short", 16)) {
200 rv = ecc_export_full(out, &out_len, PK_PRIVATE|PK_CURVEOID, &self->key);
201 if (rv != CRYPT_OK) croak("FATAL: ecc_export(PK_PRIVATE|PK_CURVEOID) failed: %s", error_to_string(rv));
202 RETVAL = newSVpvn((char*)out, out_len);
203 }
204 else if (strnEQ(type, "private", 7)) {
193205 rv = ecc_export_full(out, &out_len, PK_PRIVATE, &self->key);
194206 if (rv != CRYPT_OK) croak("FATAL: ecc_export(PK_PRIVATE) failed: %s", error_to_string(rv));
207 RETVAL = newSVpvn((char*)out, out_len);
208 }
209 else if (strnEQ(type, "public_short", 15)) {
210 rv = ecc_export_full(out, &out_len, PK_PUBLIC|PK_CURVEOID, &self->key);
211 if (rv != CRYPT_OK) croak("FATAL: ecc_export(PK_PUBLIC|PK_CURVEOID) failed: %s", error_to_string(rv));
195212 RETVAL = newSVpvn((char*)out, out_len);
196213 }
197214 else if (strnEQ(type, "public", 6)) {
433433 my ($self, $type, $password, $cipher) = @_;
434434 my $key = $self->export_key_der($type||'');
435435 return unless $key;
436 return der_to_pem($key, "EC PRIVATE KEY", $password, $cipher) if $type eq 'private';
437 return der_to_pem($key, "PUBLIC KEY") if $type eq 'public' || $type eq 'public_compressed';
436 return der_to_pem($key, "EC PRIVATE KEY", $password, $cipher) if substr($type, 0, 7) eq 'private';
437 return der_to_pem($key, "PUBLIC KEY") if substr($type,0, 6) eq 'public';
438438 }
439439
440440 sub export_key_jwk {
10261026 #or
10271027 my $public_der = $pk->export_key_der('public');
10281028
1029 Since CryptX-0.36 C<export_key_der> can also export keys in a format
1030 that does not explicitely contain curve parameters but only curve OID.
1031
1032 my $private_der = $pk->export_key_der('private_short');
1033 #or
1034 my $public_der = $pk->export_key_der('public_short');
1035
10291036 =head2 export_key_pem
10301037
10311038 my $private_pem = $pk->export_key_pem('private');
10321039 #or
10331040 my $public_pem = $pk->export_key_pem('public');
1041
1042 Since CryptX-0.36 C<export_key_pem> can also export keys in a format
1043 that does not explicitely contain curve parameters but only curve OID.
1044
1045 my $private_pem = $pk->export_key_pem('private_short');
1046 #or
1047 my $public_pem = $pk->export_key_pem('public_short');
10341048
10351049 Support for password protected PEM keys
10361050
7373 ltc/pk/dsa/dsa_import.o ltc/pk/dsa/dsa_import_hex.o ltc/pk/dsa/dsa_make_key.o ltc/pk/dsa/dsa_shared_secret.o \
7474 ltc/pk/dsa/dsa_sign_hash.o ltc/pk/dsa/dsa_verify_hash.o ltc/pk/dsa/dsa_verify_key.o ltc/pk/ecc/ecc.o \
7575 ltc/pk/ecc/ecc_ansi_x963_export.o ltc/pk/ecc/ecc_ansi_x963_import.o ltc/pk/ecc/ecc_decrypt_key.o \
76 ltc/pk/ecc/ecc_dp_clear.o ltc/pk/ecc/ecc_dp_from_oid.o ltc/pk/ecc/ecc_dp_from_params.o ltc/pk/ecc/ecc_dp_init.o \
77 ltc/pk/ecc/ecc_dp_set.o ltc/pk/ecc/ecc_encrypt_key.o ltc/pk/ecc/ecc_export.o ltc/pk/ecc/ecc_export_full.o \
76 ltc/pk/ecc/ecc_dp_clear.o ltc/pk/ecc/ecc_dp_fill_from_sets.o ltc/pk/ecc/ecc_dp_from_oid.o \
77 ltc/pk/ecc/ecc_dp_from_params.o ltc/pk/ecc/ecc_dp_init.o ltc/pk/ecc/ecc_dp_set.o \
78 ltc/pk/ecc/ecc_encrypt_key.o ltc/pk/ecc/ecc_export.o ltc/pk/ecc/ecc_export_full.o \
7879 ltc/pk/ecc/ecc_export_raw.o ltc/pk/ecc/ecc_free.o ltc/pk/ecc/ecc_get_size.o ltc/pk/ecc/ecc_import.o \
7980 ltc/pk/ecc/ecc_import_full.o ltc/pk/ecc/ecc_import_pkcs8.o ltc/pk/ecc/ecc_import_raw.o \
8081 ltc/pk/ecc/ecc_make_key.o ltc/pk/ecc/ecc_shared_secret.o ltc/pk/ecc/ecc_sign_hash.o ltc/pk/ecc/ecc_sizes.o \
7373 ltc/pk/dsa/dsa_import.obj ltc/pk/dsa/dsa_import_hex.obj ltc/pk/dsa/dsa_make_key.obj ltc/pk/dsa/dsa_shared_secret.obj \
7474 ltc/pk/dsa/dsa_sign_hash.obj ltc/pk/dsa/dsa_verify_hash.obj ltc/pk/dsa/dsa_verify_key.obj ltc/pk/ecc/ecc.obj \
7575 ltc/pk/ecc/ecc_ansi_x963_export.obj ltc/pk/ecc/ecc_ansi_x963_import.obj ltc/pk/ecc/ecc_decrypt_key.obj \
76 ltc/pk/ecc/ecc_dp_clear.obj ltc/pk/ecc/ecc_dp_from_oid.obj ltc/pk/ecc/ecc_dp_from_params.obj ltc/pk/ecc/ecc_dp_init.obj \
77 ltc/pk/ecc/ecc_dp_set.obj ltc/pk/ecc/ecc_encrypt_key.obj ltc/pk/ecc/ecc_export.obj ltc/pk/ecc/ecc_export_full.obj \
76 ltc/pk/ecc/ecc_dp_clear.obj ltc/pk/ecc/ecc_dp_fill_from_sets.obj ltc/pk/ecc/ecc_dp_from_oid.obj \
77 ltc/pk/ecc/ecc_dp_from_params.obj ltc/pk/ecc/ecc_dp_init.obj ltc/pk/ecc/ecc_dp_set.obj \
78 ltc/pk/ecc/ecc_encrypt_key.obj ltc/pk/ecc/ecc_export.obj ltc/pk/ecc/ecc_export_full.obj \
7879 ltc/pk/ecc/ecc_export_raw.obj ltc/pk/ecc/ecc_free.obj ltc/pk/ecc/ecc_get_size.obj ltc/pk/ecc/ecc_import.obj \
7980 ltc/pk/ecc/ecc_import_full.obj ltc/pk/ecc/ecc_import_pkcs8.obj ltc/pk/ecc/ecc_import_raw.obj \
8081 ltc/pk/ecc/ecc_make_key.obj ltc/pk/ecc/ecc_shared_secret.obj ltc/pk/ecc/ecc_sign_hash.obj ltc/pk/ecc/ecc_sizes.obj \
22 enum {
33 PK_PUBLIC=0,
44 PK_PRIVATE=1,
5 PK_PUBLIC_COMPRESSED=2 /* used only when exporting public ECC key */
5 PK_PUBLIC_COMPRESSED=2, /* used only when exporting public ECC key */
6 PK_CURVEOID=4 /* used only when exporting public ECC key */
67 };
78
89 /* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */
297298 int ecc_get_size(ecc_key *key);
298299
299300 int ecc_dp_init(ltc_ecc_set_type *dp);
300 int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name);
301 int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name, char *oid);
301302 int ecc_dp_set_bn(ltc_ecc_set_type *dp, void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor);
302303 int ecc_dp_set_by_oid(ltc_ecc_set_type *dp, unsigned long *oid, unsigned long oidsize);
304 int ecc_dp_fill_from_sets(ltc_ecc_set_type *dp);
303305 int ecc_dp_clear(ltc_ecc_set_type *dp);
304
305306
306307 int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
307308 int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);
2626 if (dp->order != NULL) { XFREE(dp->order); dp->order = NULL; }
2727 if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; }
2828 if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; }
29 dp->cofactor = 0;
29 dp->cofactor = 0;
30 dp->oid.OIDlen = 0;
3031
3132 return CRYPT_OK;
3233 }
0 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
1 *
2 * LibTomCrypt is a library that provides various cryptographic
3 * algorithms in a highly modular and flexible manner.
4 *
5 * The library is free for all purposes without any express
6 * guarantee it works.
7 *
8 */
9
10 #include "tomcrypt.h"
11
12 #ifdef LTC_MECC
13
14 /* search known curve by curve parameters and fill in missing parameters into dp
15 * we assume every parameter has the same case (usually uppercase) and no leading zeros
16 */
17 int ecc_dp_fill_from_sets(ltc_ecc_set_type *dp)
18 {
19 ltc_ecc_set_type params;
20 int x;
21
22 if (!dp) return CRYPT_INVALID_ARG;
23 if (dp->oid.OIDlen > 0) return CRYPT_OK;
24 if (!dp->prime || !dp->A || !dp->B || !dp->order || !dp->Gx || !dp->Gy || dp->cofactor == 0) return CRYPT_INVALID_ARG;
25
26 for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
27 if (XSTRCMP(ltc_ecc_sets[x].prime, dp->prime) == 0 &&
28 XSTRCMP(ltc_ecc_sets[x].A, dp->A) == 0 &&
29 XSTRCMP(ltc_ecc_sets[x].B, dp->B) == 0 &&
30 XSTRCMP(ltc_ecc_sets[x].order, dp->order) == 0 &&
31 XSTRCMP(ltc_ecc_sets[x].Gx, dp->Gx) == 0 &&
32 XSTRCMP(ltc_ecc_sets[x].Gy, dp->Gy) == 0 &&
33 ltc_ecc_sets[x].cofactor == dp->cofactor) {
34
35 params = ltc_ecc_sets[x];
36
37 /* copy oid */
38 dp->oid.OIDlen = params.oid.OIDlen;
39 XMEMCPY(dp->oid.OID, params.oid.OID, dp->oid.OIDlen * sizeof(dp->oid.OID[0]));
40
41 /* copy name */
42 if (dp->name != NULL) XFREE(dp->name);
43 if ((dp->name = XMALLOC(1+strlen(params.name))) == NULL) return CRYPT_MEM;
44 strcpy(dp->name, params.name);
45
46 return CRYPT_OK;
47 }
48 }
49
50 return CRYPT_INVALID_ARG;
51 }
52
53 #endif
6060 len = (unsigned long)strlen(ltc_ecc_sets[i].name);
6161 if ((dp->name = XMALLOC(1+len)) == NULL) goto cleanup7;
6262 strncpy(dp->name, ltc_ecc_sets[i].name, 1+len);
63 /* oid */
64 dp->oid.OIDlen = ltc_ecc_sets[i].oid.OIDlen;
65 XMEMCPY(dp->oid.OID, ltc_ecc_sets[i].oid.OID, dp->oid.OIDlen * sizeof(dp->oid.OID[0]));
6366 /* done - success */
6467 return CRYPT_OK;
6568
5454 /* cofactor & size */
5555 dp->cofactor = cofactor;
5656 dp->size = mp_unsigned_bin_size(prime);
57 /* name */
58 if ((dp->name = XMALLOC(7)) == NULL) goto cleanup7;
59 strcpy(dp->name, "custom"); /* XXX-TODO check this */
57 /* see if we can fill in the missing parameters from known curves */
58 if ((ecc_dp_fill_from_sets(dp)) != CRYPT_OK) {
59 /* custom name */
60 if ((dp->name = XMALLOC(7)) == NULL) goto cleanup7;
61 strcpy(dp->name, "custom"); /* XXX-TODO check this */
62 /* no oid */
63 dp->oid.OIDlen = 0;
64 }
6065 /* done - success */
6166 return CRYPT_OK;
6267
1212 */
1313
1414 #include "tomcrypt.h"
15 #include <errno.h>
1516
1617 #ifdef LTC_MECC
1718
18 int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name)
19 int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name, char *oid)
1920 {
2021 unsigned long l_name, l_prime, l_A, l_B, l_order, l_Gx, l_Gy;
2122
2223 if (!dp || !ch_prime || !ch_A || !ch_B || !ch_order || !ch_Gx || !ch_Gy || cofactor==0) return CRYPT_INVALID_ARG;
2324
24 l_name = (unsigned long)strlen(ch_name);
2525 l_prime = (unsigned long)strlen(ch_prime);
2626 l_A = (unsigned long)strlen(ch_A);
2727 l_B = (unsigned long)strlen(ch_B);
4747 if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; }
4848 if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; }
4949
50 dp->name = XMALLOC(1+l_name); strncpy(dp->name, ch_name, 1+l_name);
5150 dp->prime = XMALLOC(1+l_prime); strncpy(dp->prime, ch_prime, 1+l_prime);
5251 dp->A = XMALLOC(1+l_A); strncpy(dp->A, ch_A, 1+l_A);
5352 dp->B = XMALLOC(1+l_B); strncpy(dp->B, ch_B, 1+l_B);
5554 dp->Gx = XMALLOC(1+l_Gx); strncpy(dp->Gx, ch_Gx, 1+l_Gx);
5655 dp->Gy = XMALLOC(1+l_Gy); strncpy(dp->Gy, ch_Gy, 1+l_Gy);
5756
57 /* optional parameters */
58 if (ch_name == NULL && oid == NULL) {
59 (void)ecc_dp_fill_from_sets(dp);
60 }
61 else {
62 if (ch_name != NULL) {
63 l_name = (unsigned long)strlen(ch_name);
64 dp->name = XMALLOC(1+l_name);
65 strncpy(dp->name, ch_name, 1+l_name);
66 }
67
68 if (oid != NULL) {
69 char *end_ptr;
70 unsigned int i = 0;
71 unsigned long val;
72
73 end_ptr = oid;
74 while (i < sizeof(dp->oid.OID)/sizeof(dp->oid.OID[0]) && *oid != '\0') {
75 errno = 0;
76 val = strtoul(oid, &end_ptr, 10);
77 if (errno != 0 || oid == end_ptr) break; // parsing failed
78 if (val > 0xFFFFFFFF) break; // x64 check
79 dp->oid.OID[i++] = val;
80 oid = end_ptr;
81 if (*oid != '.') break;
82 oid++;
83 }
84 if (i == 0 || *end_ptr != '\0') return CRYPT_INVALID_ARG;
85 dp->oid.OIDlen = i;
86 }
87 }
88
89 /* in case the parameters are really custom (unlikely) */
90 if (dp->name == NULL) {
91 dp->name = XMALLOC(7);
92 strcpy(dp->name, "custom");
93 dp->oid.OIDlen = 0;
94 }
95
5896 return CRYPT_OK;
5997 }
6098
3232 unsigned long len_a, len_b, len_k, len_g, len_xy;
3333 unsigned long cofactor, one = 1;
3434 oid_st oid;
35 ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4];
35 ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], asn_ecparams[1];
3636
3737 LTC_ARGCHK(out != NULL);
3838 LTC_ARGCHK(outlen != NULL);
7777 /* we support only prime-field EC */
7878 if ((err = pk_get_oid(EC_PRIME_FIELD, &oid)) != CRYPT_OK) goto error;
7979
80 /* FieldID SEQUENCE */
81 LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid.OID, oid.OIDlen);
82 LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
80 if (type & PK_CURVEOID) {
81 /* from http://tools.ietf.org/html/rfc5912
8382
84 /* Curve SEQUENCE */
85 LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a);
86 LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b);
83 ECParameters ::= CHOICE {
84 namedCurve CURVE.&id({NamedCurve}) # OBJECT
85 }
86 */
8787
88 /* ECParameters SEQUENCE */
89 LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
90 LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
91 LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL);
92 LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g);
93 LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
94 LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
88 /* BEWARE: exporting PK_CURVEOID with custom OID means we're unable to read the curve again */
89 if (key->dp->oid.OIDlen == 0) { err = CRYPT_INVALID_ARG; goto error; }
90
91 /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */
92 LTC_SET_ASN1(asn_ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp->oid.OID, key->dp->oid.OIDlen);
93 type &= ~PK_CURVEOID;
94 }
95 else {
96 /* from http://tools.ietf.org/html/rfc3279
97
98 ECParameters ::= SEQUENCE { # SEQUENCE
99 version INTEGER { ecpVer1(1) } (ecpVer1), # INTEGER :01
100 FieldID ::= SEQUENCE { # SEQUENCE
101 fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field
102 parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER
103 }
104 Curve ::= SEQUENCE { # SEQUENCE
105 a FieldElement ::= OCTET STRING # OCTET STRING
106 b FieldElement ::= OCTET STRING # OCTET STRING
107 seed BIT STRING OPTIONAL
108 }
109 base ECPoint ::= OCTET STRING # OCTET STRING
110 order INTEGER, # INTEGER
111 cofactor INTEGER OPTIONAL # INTEGER
112 }
113 */
114
115 /* FieldID SEQUENCE */
116 LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid.OID, oid.OIDlen);
117 LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
118
119 /* Curve SEQUENCE */
120 LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a);
121 LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b);
122
123 /* ECParameters SEQUENCE */
124 LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
125 LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
126 LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL);
127 LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g);
128 LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
129 LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
130
131 /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */
132 LTC_SET_ASN1(asn_ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
133 }
95134
96135 if (type == PK_PRIVATE) {
97136 /* private key format: http://tools.ietf.org/html/rfc5915
99138 ECPrivateKey ::= SEQUENCE { # SEQUENCE
100139 version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), # INTEGER :01
101140 privateKey OCTET STRING, # OCTET STRING
102 [0] ECParameters ::= SEQUENCE { # SEQUENCE
103 version INTEGER { ecpVer1(1) } (ecpVer1), # INTEGER :01
104 FieldID ::= SEQUENCE { # SEQUENCE
105 fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field
106 parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER
107 }
108 Curve ::= SEQUENCE { # SEQUENCE
109 a FieldElement ::= OCTET STRING # OCTET STRING
110 b FieldElement ::= OCTET STRING # OCTET STRING
111 seed BIT STRING OPTIONAL
112 }
113 base ECPoint ::= OCTET STRING # OCTET STRING
114 order INTEGER, # INTEGER
115 cofactor INTEGER OPTIONAL # INTEGER
116 }
117 [1] publicKey # BIT STRING
141 [0] ECParameters # see above
142 [1] publicKey # BIT STRING
118143 }
119144 */
120145
123148 if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; }
124149 if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) goto error;
125150
126 LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
127 LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k);
128 LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
129 LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy);
151 LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
152 LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k);
153 LTC_SET_ASN1(seq_priv, 2, asn_ecparams[0].type, asn_ecparams[0].data, asn_ecparams[0].size);
154 LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy);
130155 seq_priv[2].tag = 0xA0;
131156 seq_priv[3].tag = 0xA1;
132157
138163 SubjectPublicKeyInfo ::= SEQUENCE { # SEQUENCE
139164 AlgorithmIdentifier ::= SEQUENCE { # SEQUENCE
140165 algorithm OBJECT IDENTIFIER # OBJECT :id-ecPublicKey
141 ECParameters ::= SEQUENCE { # SEQUENCE
142 version INTEGER { ecpVer1(1) } (ecpVer1), # INTEGER :01
143 FieldID ::= SEQUENCE { # SEQUENCE
144 fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field
145 parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER
146 }
147 Curve ::= SEQUENCE { # SEQUENCE
148 a FieldElement ::= OCTET STRING # OCTET STRING
149 b FieldElement ::= OCTET STRING # OCTET STRING
150 seed BIT STRING OPTIONAL
151 }
152 base ECPoint ::= OCTET STRING # OCTET STRING
153 order INTEGER, # INTEGER
154 cofactor INTEGER OPTIONAL # INTEGER
155 }
166 ECParameters # see above
156167 }
157168 subjectPublicKey BIT STRING # BIT STRING
158169 }
159170 */
160
161171 err = der_encode_subject_public_key_info( out, outlen,
162172 PKA_EC, bin_xy, len_xy,
163 LTC_ASN1_SEQUENCE, seq_ecparams, 6 );
173 asn_ecparams[0].type, asn_ecparams[0].data, asn_ecparams[0].size );
164174 }
165175
166176 error:
00 use strict;
11 use warnings;
2 use Test::More tests => 108;
2 use Test::More tests => 121;
33
44 use Crypt::PK::ECC qw(ecc_encrypt ecc_decrypt ecc_sign_message ecc_verify_message ecc_sign_hash ecc_verify_hash ecc_shared_secret);
55
136136 #ok($k->export_key_pem('public'), 'export_key_pem pub');
137137 ok($k->export_key_der('private'), 'export_key_der pri');
138138 ok($k->export_key_der('public'), 'export_key_der pub');
139 ok($k->export_key_der('private_short'), 'export_key_der pri_short');
140 ok($k->export_key_der('public_short'), 'export_key_der pub_short');
139141 }
140142
141143 {
157159 }
158160
159161 for my $priv (qw/openssl_ec-short.pem openssl_ec-short.der/) {
160 my $k = Crypt::PK::ECC->new("t/data/$priv");
162 my $f = "t/data/$priv";
163 my $k = Crypt::PK::ECC->new($f);
161164 ok($k, "load $priv");
162165 ok($k->is_private, "is_private $priv");
163166 is($k->size, 32, "size $priv");
164167 is(uc($k->key2hash->{pub_x}), 'A01532A3C0900053DE60FBEFEFCCA58793301598D308B41E6F4E364E388C2711', "key2hash $priv");
165168 is(uc($k->curve2hash->{prime}), 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', "curve2hash $priv");
166169 is($k->key2hash->{curve_name}, "secp256r1", "EC curve_name is lowercase");
170 is($k->export_key_der('private_short'), read_file($f), 'export_key_der private_oid') if (substr($priv, -3) eq "der");
171 is($k->export_key_pem('private_short'), read_file($f), 'export_key_pem private_oid') if (substr($priv, -3) eq "pem");
167172 }
168173
169174 for my $pub (qw/openssl_ec-short.pub.pem openssl_ec-short.pub.der/) {
170 my $k = Crypt::PK::ECC->new("t/data/$pub");
175 my $f = "t/data/$pub";
176 my $k = Crypt::PK::ECC->new($f);
171177 ok($k, "load $pub");
172178 ok(!$k->is_private, "is_private $pub");
173179 is($k->size, 32, "$pub size");
174180 is(uc($k->key2hash->{pub_x}), 'A01532A3C0900053DE60FBEFEFCCA58793301598D308B41E6F4E364E388C2711', "key2hash $pub");
175181 is($k->key2hash->{curve_name}, "secp256r1", "EC curve_name is lowercase");
182 is($k->export_key_der('public_short'), read_file($f), 'export_key_der public_short') if (substr($pub, -3) eq "der");
183 is($k->export_key_pem('public_short'), read_file($f), 'export_key_pem public_short') if (substr($pub, -3) eq "pem");
176184 }
177185
178186 {
180188 eval { $k->export_key_pem('public'); };
181189 ok($@, 'key not generated');
182190
191 # known curves lookup
183192 my $params = $Crypt::PK::ECC::curve{secp384r1};
193 $k = Crypt::PK::ECC->new;
184194 ok($k->generate_key($params), "generate_key hash params");
185 }
195 is($k->key2hash->{curve_name}, 'secp384r1', "key2hash curve_name");
196 is($k->key2hash->{curve_oid}, $params->{oid}, "key2hash curve_oid");
197 ok($k->export_key_der('private_short'), "export_key_der auto oid");
198
199 $k = Crypt::PK::ECC->new;
200 ok($k->generate_key({ %$params, A => '0' }), "generate_key invalid auto oid");
201 is($k->key2hash->{curve_name}, 'custom', "key2hash custom curve_name");
202 ok(!exists($k->key2hash->{curve_oid}), "key2hash curve_oid doesn't exist");
203 eval { $k->export_key_der('private_short'); };
204 ok($@, "export_key_der invalid auto oid");
205 }