mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
Fix typo in rsautl.
Add support for settable verify time in X509_verify_cert(). Document rsautl utility.
This commit is contained in:
parent
4af6e2432b
commit
bbb720034a
92
CHANGES
92
CHANGES
@ -3,57 +3,61 @@
|
||||
_______________
|
||||
|
||||
Changes between 0.9.5a and 0.9.6 [xx XXX 2000]
|
||||
|
||||
*) Phase 2 verify code reorganisation. The certificate
|
||||
verify code now looks up an issuer certificate by a
|
||||
number of criteria: subject name, authority key id
|
||||
and key usage. It also verifies self signed certificates
|
||||
by the same criteria. The main comparison function is
|
||||
X509_check_issued() which performs these checks.
|
||||
|
||||
Lot of changes were necessary in order to support this
|
||||
without completely rewriting the lookup code.
|
||||
|
||||
Authority and subject key identifier are now cached.
|
||||
|
||||
The LHASH 'certs' is X509_STORE has now been replaced
|
||||
by a STACK_OF(X509_OBJECT). This is mainly because an
|
||||
LHASH can't store or retrieve multiple objects with
|
||||
the same hash value.
|
||||
|
||||
As a result various functions (which were all internal
|
||||
use only) have changed to handle the new X509_STORE
|
||||
structure. This will break anything that messed round
|
||||
with X509_STORE internally.
|
||||
*) Allow the verify time to be set by an application,
|
||||
rather than always using the current time.
|
||||
[Steve Henson]
|
||||
|
||||
*) Phase 2 verify code reorganisation. The certificate
|
||||
verify code now looks up an issuer certificate by a
|
||||
number of criteria: subject name, authority key id
|
||||
and key usage. It also verifies self signed certificates
|
||||
by the same criteria. The main comparison function is
|
||||
X509_check_issued() which performs these checks.
|
||||
|
||||
The functions X509_STORE_add_cert() now checks for an
|
||||
exact match, rather than just subject name.
|
||||
Lot of changes were necessary in order to support this
|
||||
without completely rewriting the lookup code.
|
||||
|
||||
The X509_STORE API doesn't directly support the retrieval
|
||||
of multiple certificates matching a given criteria, however
|
||||
this can be worked round by performing a lookup first
|
||||
(which will fill the cache with candidate certificates)
|
||||
and then examining the cache for matches. This is probably
|
||||
the best we can do without throwing out X509_LOOKUP
|
||||
entirely (maybe later...).
|
||||
Authority and subject key identifier are now cached.
|
||||
|
||||
The X509_VERIFY_CTX structure has been enhanced considerably.
|
||||
The LHASH 'certs' is X509_STORE has now been replaced
|
||||
by a STACK_OF(X509_OBJECT). This is mainly because an
|
||||
LHASH can't store or retrieve multiple objects with
|
||||
the same hash value.
|
||||
|
||||
As a result various functions (which were all internal
|
||||
use only) have changed to handle the new X509_STORE
|
||||
structure. This will break anything that messed round
|
||||
with X509_STORE internally.
|
||||
|
||||
All certificate lookup operations now go via a get_issuer()
|
||||
callback. Although this currently uses an X509_STORE it
|
||||
can be replaced by custom lookups. This is a simple way
|
||||
to bypass the X509_STORE hackery necessary to make this
|
||||
work and makes it possible to use more efficient techniques
|
||||
in future. A very simple version which uses a simple
|
||||
STACK for its trusted certificate store is also provided
|
||||
using X509_STORE_CTX_trusted_stack().
|
||||
The functions X509_STORE_add_cert() now checks for an
|
||||
exact match, rather than just subject name.
|
||||
|
||||
The verify_cb() and verify() callbacks now have equivalents
|
||||
in the X509_STORE_CTX structure.
|
||||
The X509_STORE API doesn't directly support the retrieval
|
||||
of multiple certificates matching a given criteria, however
|
||||
this can be worked round by performing a lookup first
|
||||
(which will fill the cache with candidate certificates)
|
||||
and then examining the cache for matches. This is probably
|
||||
the best we can do without throwing out X509_LOOKUP
|
||||
entirely (maybe later...).
|
||||
|
||||
X509_STORE_CTX also has a 'flags' field which can be used
|
||||
to customise the verify behaviour.
|
||||
[Steve Henson]
|
||||
The X509_VERIFY_CTX structure has been enhanced considerably.
|
||||
|
||||
All certificate lookup operations now go via a get_issuer()
|
||||
callback. Although this currently uses an X509_STORE it
|
||||
can be replaced by custom lookups. This is a simple way
|
||||
to bypass the X509_STORE hackery necessary to make this
|
||||
work and makes it possible to use more efficient techniques
|
||||
in future. A very simple version which uses a simple
|
||||
STACK for its trusted certificate store is also provided
|
||||
using X509_STORE_CTX_trusted_stack().
|
||||
|
||||
The verify_cb() and verify() callbacks now have equivalents
|
||||
in the X509_STORE_CTX structure.
|
||||
|
||||
X509_STORE_CTX also has a 'flags' field which can be used
|
||||
to customise the verify behaviour.
|
||||
[Steve Henson]
|
||||
|
||||
*) Add new PKCS#7 signing option PKCS7_NOSMIMECAP which
|
||||
excludes S/MIME capabilities.
|
||||
|
@ -141,7 +141,7 @@ int MAIN(int argc, char **argv)
|
||||
argv++;
|
||||
}
|
||||
|
||||
if(need_priv && (key_type == KEY_PRIVKEY)) {
|
||||
if(need_priv && (key_type != KEY_PRIVKEY)) {
|
||||
BIO_printf(bio_err, "A private key is needed for this operation\n");
|
||||
goto end;
|
||||
}
|
||||
|
@ -800,7 +800,9 @@ RSA *RSAPrivateKey_dup(RSA *rsa);
|
||||
|
||||
#endif /* !SSLEAY_MACROS */
|
||||
|
||||
int X509_cmp_time(ASN1_TIME *s, time_t *t);
|
||||
int X509_cmp_current_time(ASN1_TIME *s);
|
||||
ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
|
||||
ASN1_TIME * X509_gmtime_adj(ASN1_TIME *s, long adj);
|
||||
|
||||
const char * X509_get_default_cert_area(void );
|
||||
|
@ -429,6 +429,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
|
||||
int i,ok=0,n;
|
||||
X509 *xs,*xi;
|
||||
EVP_PKEY *pkey=NULL;
|
||||
time_t *ptime;
|
||||
int (*cb)();
|
||||
|
||||
cb=ctx->verify_cb;
|
||||
@ -438,8 +439,9 @@ static int internal_verify(X509_STORE_CTX *ctx)
|
||||
ctx->error_depth=n-1;
|
||||
n--;
|
||||
xi=sk_X509_value(ctx->chain,n);
|
||||
if (X509_NAME_cmp(X509_get_subject_name(xi),
|
||||
X509_get_issuer_name(xi)) == 0)
|
||||
if(ctx->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->check_time;
|
||||
else ptime = NULL;
|
||||
if (ctx->check_issued(ctx, xi, xi))
|
||||
xs=xi;
|
||||
else
|
||||
{
|
||||
@ -485,7 +487,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
|
||||
EVP_PKEY_free(pkey);
|
||||
pkey=NULL;
|
||||
|
||||
i=X509_cmp_current_time(X509_get_notBefore(xs));
|
||||
i=X509_cmp_time(X509_get_notBefore(xs), ptime);
|
||||
if (i == 0)
|
||||
{
|
||||
ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
|
||||
@ -503,7 +505,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
|
||||
xs->valid=1;
|
||||
}
|
||||
|
||||
i=X509_cmp_current_time(X509_get_notAfter(xs));
|
||||
i=X509_cmp_time(X509_get_notAfter(xs), ptime);
|
||||
if (i == 0)
|
||||
{
|
||||
ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
|
||||
@ -540,6 +542,11 @@ end:
|
||||
}
|
||||
|
||||
int X509_cmp_current_time(ASN1_TIME *ctm)
|
||||
{
|
||||
return X509_cmp_time(ctm, NULL);
|
||||
}
|
||||
|
||||
int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time)
|
||||
{
|
||||
char *str;
|
||||
ASN1_TIME atm;
|
||||
@ -594,7 +601,7 @@ int X509_cmp_current_time(ASN1_TIME *ctm)
|
||||
atm.length=sizeof(buff2);
|
||||
atm.data=(unsigned char *)buff2;
|
||||
|
||||
X509_gmtime_adj(&atm,-offset*60);
|
||||
X509_time_adj(&atm,-offset*60, cmp_time);
|
||||
|
||||
if(ctm->type == V_ASN1_UTCTIME)
|
||||
{
|
||||
@ -614,10 +621,17 @@ int X509_cmp_current_time(ASN1_TIME *ctm)
|
||||
}
|
||||
|
||||
ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
|
||||
{
|
||||
return X509_time_adj(s, adj, NULL);
|
||||
}
|
||||
|
||||
ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
time(&t);
|
||||
if(in_tm) t = *in_tm;
|
||||
else time(&t);
|
||||
|
||||
t+=adj;
|
||||
if(!s) return ASN1_TIME_set(s, t);
|
||||
if(s->type == V_ASN1_UTCTIME) return(ASN1_UTCTIME_set(s,t));
|
||||
@ -855,6 +869,17 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
|
||||
memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
|
||||
}
|
||||
|
||||
void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, long flags)
|
||||
{
|
||||
ctx->flags |= flags;
|
||||
}
|
||||
|
||||
void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t)
|
||||
{
|
||||
ctx->check_time = t;
|
||||
ctx->flags |= X509_V_FLAG_USE_CHECK_TIME;
|
||||
}
|
||||
|
||||
IMPLEMENT_STACK_OF(X509)
|
||||
IMPLEMENT_ASN1_SET_OF(X509)
|
||||
|
||||
|
@ -380,6 +380,8 @@ int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
|
||||
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
|
||||
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
|
||||
int purpose, int trust);
|
||||
void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, long flags);
|
||||
void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
181
doc/apps/rsautl.pod
Normal file
181
doc/apps/rsautl.pod
Normal file
@ -0,0 +1,181 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
rsautl - RSA utility
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<openssl> B<rsautl>
|
||||
[B<-in file>]
|
||||
[B<-out file>]
|
||||
[B<-inkey file>]
|
||||
[B<-pubin>]
|
||||
[B<-certin>]
|
||||
[B<-sign>]
|
||||
[B<-verify>]
|
||||
[B<-encrypt>]
|
||||
[B<-decrypt>]
|
||||
[B<-pkcs>]
|
||||
[B<-ssl>]
|
||||
[B<-raw>]
|
||||
[B<-hexdump>]
|
||||
[B<-asn1parse>]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<rsautl> command can be used to sign, verify, encrypt and decrypt
|
||||
data using the RSA algorithm.
|
||||
|
||||
=head1 COMMAND OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<-in filename>
|
||||
|
||||
This specifies the input filename to read data from or standard input
|
||||
if this option is not specified.
|
||||
|
||||
=item B<-out filename>
|
||||
|
||||
specifies the output filename to write to or standard output by
|
||||
default.
|
||||
|
||||
=item B<-inkey file>
|
||||
|
||||
the input key file, by default it should be an RSA private key.
|
||||
|
||||
=item B<-pubin>
|
||||
|
||||
the input file is an RSA public key.
|
||||
|
||||
=item B<-certin>
|
||||
|
||||
the input is a certificate containing an RSA public key.
|
||||
|
||||
=item B<-sign>
|
||||
|
||||
sign the input data and output the signed result. This requires
|
||||
and RSA private key.
|
||||
|
||||
=item B<-verify>
|
||||
|
||||
verify the input data and output the recovered data.
|
||||
|
||||
=item B<-encrypt>
|
||||
|
||||
encrypt the input data using an RSA public key.
|
||||
|
||||
=item B<-decrypt>
|
||||
|
||||
decrypt the input data using an RSA private key.
|
||||
|
||||
=item B<-pkcs, -ssl, -raw>
|
||||
|
||||
the padding to use, PKCS#1 v1.5 (the default) SSL v2 or no padding
|
||||
respectively.
|
||||
|
||||
=item B<-hexdump>
|
||||
|
||||
hex dump the output data.
|
||||
|
||||
=item B<-asn1parse>
|
||||
|
||||
asn1parse the output data, this is useful when combined with the
|
||||
B<-verify> option.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
B<rsautl> because it uses the RSA algorithm directly can only be
|
||||
used to sign or verify small pieces of data.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Sign the some data using a private key:
|
||||
|
||||
openssl rsautl -sign -in file -inkey key.pem -out sig
|
||||
|
||||
Recover the signed data
|
||||
|
||||
openssl rsautl -sign -in sig -inkey key.pem
|
||||
|
||||
Examine the raw signed data:
|
||||
|
||||
openssl rsautl -sign -in file -inkey key.pem -raw -hexdump
|
||||
|
||||
0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
|
||||
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
|
||||
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
|
||||
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
|
||||
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
|
||||
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
|
||||
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
|
||||
0070 - ff ff ff ff 00 68 65 6c-6c 6f 20 77 6f 72 6c 64 .....hello world
|
||||
|
||||
The PKCS#1 block formatting is evident from this. If this was done using
|
||||
encrypt and decrypt the block would have been of type 2 (the second byte)
|
||||
and random padding data visible instead of the 0xff bytes.
|
||||
|
||||
It is possible to analyse the signature of certificates using this
|
||||
utility in conjunction with B<asn1parse>. Consider the self signed
|
||||
example in certs/pca-cert.pem . Running B<asn1parse> as follows yields:
|
||||
|
||||
openssl asn1parse -in pca-cert.pem
|
||||
|
||||
0:d=0 hl=4 l= 742 cons: SEQUENCE
|
||||
4:d=1 hl=4 l= 591 cons: SEQUENCE
|
||||
8:d=2 hl=2 l= 3 cons: cont [ 0 ]
|
||||
10:d=3 hl=2 l= 1 prim: INTEGER :02
|
||||
13:d=2 hl=2 l= 1 prim: INTEGER :00
|
||||
16:d=2 hl=2 l= 13 cons: SEQUENCE
|
||||
18:d=3 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
|
||||
29:d=3 hl=2 l= 0 prim: NULL
|
||||
31:d=2 hl=2 l= 92 cons: SEQUENCE
|
||||
33:d=3 hl=2 l= 11 cons: SET
|
||||
35:d=4 hl=2 l= 9 cons: SEQUENCE
|
||||
37:d=5 hl=2 l= 3 prim: OBJECT :countryName
|
||||
42:d=5 hl=2 l= 2 prim: PRINTABLESTRING :AU
|
||||
....
|
||||
599:d=1 hl=2 l= 13 cons: SEQUENCE
|
||||
601:d=2 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
|
||||
612:d=2 hl=2 l= 0 prim: NULL
|
||||
614:d=1 hl=3 l= 129 prim: BIT STRING
|
||||
|
||||
|
||||
The final BIT STRING contains the actual signature. It can be extracted with:
|
||||
|
||||
openssl asn1parse -in pca-cert.pem -out sig -noout -strparse 614
|
||||
|
||||
The certificate public key can be extracted with:
|
||||
|
||||
openssl x509 -in test/testx509.pem -pubout -noout >pubkey.pem
|
||||
|
||||
The signature can be analysed with:
|
||||
|
||||
openssl rsautl -in sig -verify -asn1parse -inkey pubkey.pem -pubin
|
||||
|
||||
0:d=0 hl=2 l= 32 cons: SEQUENCE
|
||||
2:d=1 hl=2 l= 12 cons: SEQUENCE
|
||||
4:d=2 hl=2 l= 8 prim: OBJECT :md5
|
||||
14:d=2 hl=2 l= 0 prim: NULL
|
||||
16:d=1 hl=2 l= 16 prim: OCTET STRING
|
||||
0000 - f3 46 9e aa 1a 4a 73 c9-37 ea 93 00 48 25 08 b5 .F...Js.7...H%..
|
||||
|
||||
This is the parsed version of an ASN1 DigestInfo structure. It can be seen that
|
||||
the digest used was md5. The actual part of the certificate that was signed can
|
||||
be extracted with:
|
||||
|
||||
openssl asn1parse -in pca-cert.pem -out tbs -noout -strparse 4
|
||||
|
||||
and its digest computed with:
|
||||
|
||||
openssl md5 -c tbs
|
||||
MD5(tbs)= f3:46:9e:aa:1a:4a:73:c9:37:ea:93:00:48:25:08:b5
|
||||
|
||||
which it can be seen agrees with the recovered value above.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<dgst(1)|dgst(1)>, L<rsa(1)|rsa(1)>, L<genrsa(1)|genrsa(1)>
|
Loading…
Reference in New Issue
Block a user