mirror of
https://github.com/openssl/openssl.git
synced 2025-02-17 14:32:04 +08:00
Support raw input data in apps/pkeyutl
Some signature algorithms require special treatment for digesting, such as SM2. This patch adds the ability of handling raw input data in apps/pkeyutl other than accepting only pre-hashed input data. Beside, SM2 requries an ID string when signing or verifying a piece of data, this patch also adds the ability for apps/pkeyutil to specify that ID string. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/8186)
This commit is contained in:
parent
4089b43407
commit
a7cef52f9b
169
apps/pkeyutl.c
169
apps/pkeyutl.c
@ -22,7 +22,7 @@
|
|||||||
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
||||||
const char *keyfile, int keyform, int key_type,
|
const char *keyfile, int keyform, int key_type,
|
||||||
char *passinarg, int pkey_op, ENGINE *e,
|
char *passinarg, int pkey_op, ENGINE *e,
|
||||||
const int impl);
|
const int impl, EVP_PKEY **ppkey);
|
||||||
|
|
||||||
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
|
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
|
||||||
ENGINE *e);
|
ENGINE *e);
|
||||||
@ -31,6 +31,11 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
|
|||||||
unsigned char *out, size_t *poutlen,
|
unsigned char *out, size_t *poutlen,
|
||||||
const unsigned char *in, size_t inlen);
|
const unsigned char *in, size_t inlen);
|
||||||
|
|
||||||
|
static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||||
|
const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
|
||||||
|
unsigned char *sig, int siglen,
|
||||||
|
unsigned char **out, size_t *poutlen);
|
||||||
|
|
||||||
typedef enum OPTION_choice {
|
typedef enum OPTION_choice {
|
||||||
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
|
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
|
||||||
OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
|
OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
|
||||||
@ -38,12 +43,16 @@ typedef enum OPTION_choice {
|
|||||||
OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
|
OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
|
||||||
OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
|
OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
|
||||||
OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
|
OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
|
||||||
OPT_KDFLEN, OPT_R_ENUM
|
OPT_KDFLEN, OPT_R_ENUM,
|
||||||
|
OPT_RAWIN, OPT_DIGEST
|
||||||
} OPTION_CHOICE;
|
} OPTION_CHOICE;
|
||||||
|
|
||||||
const OPTIONS pkeyutl_options[] = {
|
const OPTIONS pkeyutl_options[] = {
|
||||||
{"help", OPT_HELP, '-', "Display this summary"},
|
{"help", OPT_HELP, '-', "Display this summary"},
|
||||||
{"in", OPT_IN, '<', "Input file - default stdin"},
|
{"in", OPT_IN, '<', "Input file - default stdin"},
|
||||||
|
{"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
|
||||||
|
{"digest", OPT_DIGEST, 's',
|
||||||
|
"Specify the digest algorithm when signing the raw input data"},
|
||||||
{"out", OPT_OUT, '>', "Output file - default stdout"},
|
{"out", OPT_OUT, '>', "Output file - default stdout"},
|
||||||
{"pubin", OPT_PUBIN, '-', "Input is a public key"},
|
{"pubin", OPT_PUBIN, '-', "Input is a public key"},
|
||||||
{"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
|
{"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
|
||||||
@ -82,6 +91,7 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
BIO *in = NULL, *out = NULL;
|
BIO *in = NULL, *out = NULL;
|
||||||
ENGINE *e = NULL;
|
ENGINE *e = NULL;
|
||||||
EVP_PKEY_CTX *ctx = NULL;
|
EVP_PKEY_CTX *ctx = NULL;
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
|
char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
|
||||||
char hexdump = 0, asn1parse = 0, rev = 0, *prog;
|
char hexdump = 0, asn1parse = 0, rev = 0, *prog;
|
||||||
unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
|
unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
|
||||||
@ -97,6 +107,8 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
int kdflen = 0;
|
int kdflen = 0;
|
||||||
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
|
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
|
||||||
STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
|
STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
|
||||||
|
int rawin = 0;
|
||||||
|
const EVP_MD *md = NULL;
|
||||||
|
|
||||||
prog = opt_init(argc, argv, pkeyutl_options);
|
prog = opt_init(argc, argv, pkeyutl_options);
|
||||||
while ((o = opt_next()) != OPT_EOF) {
|
while ((o = opt_next()) != OPT_EOF) {
|
||||||
@ -203,12 +215,39 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OPT_RAWIN:
|
||||||
|
rawin = 1;
|
||||||
|
break;
|
||||||
|
case OPT_DIGEST:
|
||||||
|
if (!opt_md(opt_arg(), &md))
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argc = opt_num_rest();
|
argc = opt_num_rest();
|
||||||
if (argc != 0)
|
if (argc != 0)
|
||||||
goto opthelp;
|
goto opthelp;
|
||||||
|
|
||||||
|
if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
|
||||||
|
BIO_printf(bio_err,
|
||||||
|
"%s: -rawin can only be used with -sign or -verify\n",
|
||||||
|
prog);
|
||||||
|
goto opthelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md != NULL && !rawin) {
|
||||||
|
BIO_printf(bio_err,
|
||||||
|
"%s: -digest can only be used with -rawin\n",
|
||||||
|
prog);
|
||||||
|
goto opthelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawin && rev) {
|
||||||
|
BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
|
||||||
|
prog);
|
||||||
|
goto opthelp;
|
||||||
|
}
|
||||||
|
|
||||||
if (kdfalg != NULL) {
|
if (kdfalg != NULL) {
|
||||||
if (kdflen == 0) {
|
if (kdflen == 0) {
|
||||||
BIO_printf(bio_err,
|
BIO_printf(bio_err,
|
||||||
@ -225,7 +264,7 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
goto opthelp;
|
goto opthelp;
|
||||||
}
|
}
|
||||||
ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
|
ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
|
||||||
passinarg, pkey_op, e, engine_impl);
|
passinarg, pkey_op, e, engine_impl, &pkey);
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
BIO_printf(bio_err, "%s: Error initializing context\n", prog);
|
BIO_printf(bio_err, "%s: Error initializing context\n", prog);
|
||||||
ERR_print_errors(bio_err);
|
ERR_print_errors(bio_err);
|
||||||
@ -327,7 +366,8 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in != NULL) {
|
/* Raw input data is handled elsewhere */
|
||||||
|
if (in != NULL && !rawin) {
|
||||||
/* Read the input data */
|
/* Read the input data */
|
||||||
buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
|
buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
|
||||||
if (buf_inlen < 0) {
|
if (buf_inlen < 0) {
|
||||||
@ -346,8 +386,9 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check the input */
|
/* Sanity check the input if the input is not raw */
|
||||||
if (buf_inlen > EVP_MAX_MD_SIZE
|
if (!rawin
|
||||||
|
&& buf_inlen > EVP_MAX_MD_SIZE
|
||||||
&& (pkey_op == EVP_PKEY_OP_SIGN
|
&& (pkey_op == EVP_PKEY_OP_SIGN
|
||||||
|| pkey_op == EVP_PKEY_OP_VERIFY
|
|| pkey_op == EVP_PKEY_OP_VERIFY
|
||||||
|| pkey_op == EVP_PKEY_OP_VERIFYRECOVER)) {
|
|| pkey_op == EVP_PKEY_OP_VERIFYRECOVER)) {
|
||||||
@ -357,8 +398,13 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pkey_op == EVP_PKEY_OP_VERIFY) {
|
if (pkey_op == EVP_PKEY_OP_VERIFY) {
|
||||||
rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
|
if (rawin) {
|
||||||
buf_in, (size_t)buf_inlen);
|
rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, sig, siglen,
|
||||||
|
NULL, 0);
|
||||||
|
} else {
|
||||||
|
rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
|
||||||
|
buf_in, (size_t)buf_inlen);
|
||||||
|
}
|
||||||
if (rv == 1) {
|
if (rv == 1) {
|
||||||
BIO_puts(out, "Signature Verified Successfully\n");
|
BIO_puts(out, "Signature Verified Successfully\n");
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -371,14 +417,20 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
buf_outlen = kdflen;
|
buf_outlen = kdflen;
|
||||||
rv = 1;
|
rv = 1;
|
||||||
} else {
|
} else {
|
||||||
rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
|
if (rawin) {
|
||||||
buf_in, (size_t)buf_inlen);
|
/* rawin allocates the buffer in do_raw_keyop() */
|
||||||
}
|
rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, NULL, 0,
|
||||||
if (rv > 0 && buf_outlen != 0) {
|
&buf_out, (size_t *)&buf_outlen);
|
||||||
buf_out = app_malloc(buf_outlen, "buffer output");
|
} else {
|
||||||
rv = do_keyop(ctx, pkey_op,
|
rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
|
||||||
buf_out, (size_t *)&buf_outlen,
|
buf_in, (size_t)buf_inlen);
|
||||||
buf_in, (size_t)buf_inlen);
|
if (rv > 0 && buf_outlen != 0) {
|
||||||
|
buf_out = app_malloc(buf_outlen, "buffer output");
|
||||||
|
rv = do_keyop(ctx, pkey_op,
|
||||||
|
buf_out, (size_t *)&buf_outlen,
|
||||||
|
buf_in, (size_t)buf_inlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (rv <= 0) {
|
if (rv <= 0) {
|
||||||
if (pkey_op != EVP_PKEY_OP_DERIVE) {
|
if (pkey_op != EVP_PKEY_OP_DERIVE) {
|
||||||
@ -416,7 +468,7 @@ int pkeyutl_main(int argc, char **argv)
|
|||||||
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
||||||
const char *keyfile, int keyform, int key_type,
|
const char *keyfile, int keyform, int key_type,
|
||||||
char *passinarg, int pkey_op, ENGINE *e,
|
char *passinarg, int pkey_op, ENGINE *e,
|
||||||
const int engine_impl)
|
const int engine_impl, EVP_PKEY **ppkey)
|
||||||
{
|
{
|
||||||
EVP_PKEY *pkey = NULL;
|
EVP_PKEY *pkey = NULL;
|
||||||
EVP_PKEY_CTX *ctx = NULL;
|
EVP_PKEY_CTX *ctx = NULL;
|
||||||
@ -474,10 +526,25 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
|||||||
}
|
}
|
||||||
ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
|
ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
|
||||||
} else {
|
} else {
|
||||||
|
EC_KEY *eckey = NULL;
|
||||||
|
const EC_GROUP *group = NULL;
|
||||||
|
int nid;
|
||||||
|
|
||||||
if (pkey == NULL)
|
if (pkey == NULL)
|
||||||
goto end;
|
goto end;
|
||||||
|
/* SM2 needs a special treatment */
|
||||||
|
if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
|
||||||
|
if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL
|
||||||
|
|| (group = EC_KEY_get0_group(eckey)) == NULL
|
||||||
|
|| (nid = EC_GROUP_get_curve_name(group)) == 0)
|
||||||
|
goto end;
|
||||||
|
if (nid == NID_sm2)
|
||||||
|
EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
|
||||||
|
}
|
||||||
*pkeysize = EVP_PKEY_size(pkey);
|
*pkeysize = EVP_PKEY_size(pkey);
|
||||||
ctx = EVP_PKEY_CTX_new(pkey, impl);
|
ctx = EVP_PKEY_CTX_new(pkey, impl);
|
||||||
|
if (ppkey != NULL)
|
||||||
|
*ppkey = pkey;
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,3 +641,71 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
|
|||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TBUF_MAXSIZE 2048
|
||||||
|
|
||||||
|
static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||||
|
const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
|
||||||
|
unsigned char *sig, int siglen,
|
||||||
|
unsigned char **out, size_t *poutlen)
|
||||||
|
{
|
||||||
|
int rv = 0;
|
||||||
|
EVP_MD_CTX *mctx = NULL;
|
||||||
|
unsigned char tbuf[TBUF_MAXSIZE];
|
||||||
|
int tbuf_len = 0;
|
||||||
|
|
||||||
|
if ((mctx = EVP_MD_CTX_new()) == NULL) {
|
||||||
|
BIO_printf(bio_err, "Error: out of memory\n");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
|
||||||
|
|
||||||
|
switch(pkey_op) {
|
||||||
|
case EVP_PKEY_OP_VERIFY:
|
||||||
|
if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1)
|
||||||
|
goto end;
|
||||||
|
for (;;) {
|
||||||
|
tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
|
||||||
|
if (tbuf_len == 0)
|
||||||
|
break;
|
||||||
|
if (tbuf_len < 0) {
|
||||||
|
BIO_printf(bio_err, "Error reading raw input data\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)tbuf_len);
|
||||||
|
if (rv != 1) {
|
||||||
|
BIO_printf(bio_err, "Error verifying raw input data\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
|
||||||
|
break;
|
||||||
|
case EVP_PKEY_OP_SIGN:
|
||||||
|
if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1)
|
||||||
|
goto end;
|
||||||
|
for (;;) {
|
||||||
|
tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
|
||||||
|
if (tbuf_len == 0)
|
||||||
|
break;
|
||||||
|
if (tbuf_len < 0) {
|
||||||
|
BIO_printf(bio_err, "Error reading raw input data\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)tbuf_len);
|
||||||
|
if (rv != 1) {
|
||||||
|
BIO_printf(bio_err, "Error signing raw input data\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
|
||||||
|
if (rv == 1 && out != NULL) {
|
||||||
|
*out = app_malloc(*poutlen, "buffer output");
|
||||||
|
rv = EVP_DigestSignFinal(mctx, *out, poutlen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
EVP_MD_CTX_free(mctx);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
@ -248,6 +248,9 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx,
|
|||||||
else
|
else
|
||||||
return -2;
|
return -2;
|
||||||
return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
|
return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
|
||||||
|
} else if (strcmp(type, "sm2_id") == 0) {
|
||||||
|
return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID,
|
||||||
|
(int)strlen(value), (void *)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -2;
|
return -2;
|
||||||
|
@ -10,6 +10,8 @@ pkeyutl - public key algorithm utility
|
|||||||
B<openssl> B<pkeyutl>
|
B<openssl> B<pkeyutl>
|
||||||
[B<-help>]
|
[B<-help>]
|
||||||
[B<-in file>]
|
[B<-in file>]
|
||||||
|
[B<-rawin>]
|
||||||
|
[B<-digest algorithm>]
|
||||||
[B<-out file>]
|
[B<-out file>]
|
||||||
[B<-sigfile file>]
|
[B<-sigfile file>]
|
||||||
[B<-inkey file>]
|
[B<-inkey file>]
|
||||||
@ -55,6 +57,23 @@ Print out a usage message.
|
|||||||
This specifies the input filename to read data from or standard input
|
This specifies the input filename to read data from or standard input
|
||||||
if this option is not specified.
|
if this option is not specified.
|
||||||
|
|
||||||
|
=item B<-rawin>
|
||||||
|
|
||||||
|
This indicates that the input data is raw data, which is not hashed by any
|
||||||
|
message digest algorithm. The user can specify a digest algorithm by using
|
||||||
|
the B<-digest> option. This option can only be used with B<-sign> and
|
||||||
|
B<-verify>.
|
||||||
|
|
||||||
|
=item B<-digest algorithm>
|
||||||
|
|
||||||
|
This specifies the digest algorithm which is used to hash the input data before
|
||||||
|
signing or verifying it with the input key. This option could be omitted if the
|
||||||
|
signature algorithm does not require one (for instance, EdDSA). If this option
|
||||||
|
is omitted but the signature algorithm requires one, a default value will be
|
||||||
|
used. For signature algorithms like RSA, DSA and ECDSA, SHA-256 will be the
|
||||||
|
default digest algorithm. For SM2, it will be SM3. If this option is present,
|
||||||
|
then the B<-rawin> option must be also specified to B<pkeyutl>.
|
||||||
|
|
||||||
=item B<-out filename>
|
=item B<-out filename>
|
||||||
|
|
||||||
Specifies the output filename to write to or standard output by
|
Specifies the output filename to write to or standard output by
|
||||||
@ -300,6 +319,22 @@ this digest is assumed by default.
|
|||||||
The X25519 and X448 algorithms support key derivation only. Currently there are
|
The X25519 and X448 algorithms support key derivation only. Currently there are
|
||||||
no additional options.
|
no additional options.
|
||||||
|
|
||||||
|
=head1 SM2
|
||||||
|
|
||||||
|
The SM2 algorithm supports sign, verify, encrypt and decrypt operations. For
|
||||||
|
the sign and verify operations, SM2 requires an ID string to be passed in. The
|
||||||
|
following B<pkeyopt> value is supported:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item B<sm2_id:string>
|
||||||
|
|
||||||
|
This sets the ID string used in SM2 sign or verify operations. While verifying
|
||||||
|
an SM2 signature, the ID string must be the same one used when signing the data.
|
||||||
|
Otherwise the verification will fail.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
=head1 EXAMPLES
|
=head1 EXAMPLES
|
||||||
|
|
||||||
Sign some data using a private key:
|
Sign some data using a private key:
|
||||||
@ -338,6 +373,16 @@ Derive using the same algorithm, but read key from environment variable MYPASS:
|
|||||||
openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass:env:MYPASS \
|
openssl pkeyutl -kdf scrypt -kdflen 16 -pkeyopt_passin pass:env:MYPASS \
|
||||||
-pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
|
-pkeyopt hexsalt:aabbcc -pkeyopt N:16384 -pkeyopt r:8 -pkeyopt p:1
|
||||||
|
|
||||||
|
Sign some data using an L<SM2(7)> private key and a specific ID:
|
||||||
|
|
||||||
|
openssl pkeyutl -sign -in file -inkey sm2.key -out sig -rawin -digest sm3 \
|
||||||
|
-pkeyopt sm2_id:someid
|
||||||
|
|
||||||
|
Verify some data using an L<SM2(7)> certificate and a specific ID:
|
||||||
|
|
||||||
|
openssl pkeyutl -verify -certin -in file -inkey sm2.cert -sigfile sig \
|
||||||
|
-rawin -digest sm3 -pkeyopt sm2_id:someid
|
||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
L<genpkey(1)>, L<pkey(1)>, L<rsautl(1)>
|
L<genpkey(1)>, L<pkey(1)>, L<rsautl(1)>
|
||||||
|
13
test/certs/sm2.crt
Normal file
13
test/certs/sm2.crt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB6DCCAY6gAwIBAgIJAKH2BR6ITHZeMAoGCCqBHM9VAYN1MGgxCzAJBgNVBAYT
|
||||||
|
AkNOMQswCQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRl
|
||||||
|
c3QgT3JnMRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTAe
|
||||||
|
Fw0xOTAyMTkwNzA1NDhaFw0yMzAzMzAwNzA1NDhaMG8xCzAJBgNVBAYTAkNOMQsw
|
||||||
|
CQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRlc3QgT3Jn
|
||||||
|
MRAwDgYDVQQLDAdUZXN0IE9VMRswGQYDVQQDDBJUZXN0IFNNMiBTaWduIENlcnQw
|
||||||
|
WTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAQwqeNkWp7fiu1KZnuDkAucpM8piEzE
|
||||||
|
TL1ymrcrOBvv8mhNNkeb20asbWgFQI2zOrSM99/sXGn9rM2/usM/MlcaoxowGDAJ
|
||||||
|
BgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNIADBFAiEA9edBnAqT
|
||||||
|
TNuGIUIvXsj6/nP+AzXA9HGtAIY4nrqW8LkCIHyZzhRTlxYtgfqkDl0OK5QQRCZH
|
||||||
|
OZOfmtx613VyzXwc
|
||||||
|
-----END CERTIFICATE-----
|
5
test/certs/sm2.key
Normal file
5
test/certs/sm2.key
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgSKhk+4xGyDI+IS2H
|
||||||
|
WVfFPDxh1qv5+wtrddaIsGNXGZihRANCAAQwqeNkWp7fiu1KZnuDkAucpM8piEzE
|
||||||
|
TL1ymrcrOBvv8mhNNkeb20asbWgFQI2zOrSM99/sXGn9rM2/usM/Mlca
|
||||||
|
-----END PRIVATE KEY-----
|
43
test/recipes/20-test_pkeyutl.t
Normal file
43
test/recipes/20-test_pkeyutl.t
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#! /usr/bin/env perl
|
||||||
|
# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
|
# this file except in compliance with the License. You can obtain a copy
|
||||||
|
# in the file LICENSE in the source distribution or at
|
||||||
|
# https://www.openssl.org/source/license.html
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use File::Spec;
|
||||||
|
use OpenSSL::Test qw/:DEFAULT srctop_file/;
|
||||||
|
use OpenSSL::Test::Utils;
|
||||||
|
|
||||||
|
setup("test_pkeyutl");
|
||||||
|
|
||||||
|
plan tests => 2;
|
||||||
|
|
||||||
|
sub sign
|
||||||
|
{
|
||||||
|
# Utilize the sm2.crt as the TBS file
|
||||||
|
return run(app(([ 'openssl', 'pkeyutl', '-sign',
|
||||||
|
'-in', srctop_file('test', 'certs', 'sm2.crt'),
|
||||||
|
'-inkey', srctop_file('test', 'certs', 'sm2.key'),
|
||||||
|
'-out', 'signature.sm2', '-rawin',
|
||||||
|
'-digest', 'sm3', '-pkeyopt', 'sm2_id:someid'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub verify
|
||||||
|
{
|
||||||
|
# Utilize the sm2.crt as the TBS file
|
||||||
|
return run(app(([ 'openssl', 'pkeyutl', '-verify', '-certin',
|
||||||
|
'-in', srctop_file('test', 'certs', 'sm2.crt'),
|
||||||
|
'-inkey', srctop_file('test', 'certs', 'sm2.crt'),
|
||||||
|
'-sigfile', 'signature.sm2', '-rawin',
|
||||||
|
'-digest', 'sm3', '-pkeyopt', 'sm2_id:someid'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(sign, "Sign a piece of data using SM2");
|
||||||
|
ok(verify, "Verify an SM2 signature against a piece of data");
|
||||||
|
|
||||||
|
unlink 'signature.sm2';
|
Loading…
Reference in New Issue
Block a user