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
4
CHANGES
4
CHANGES
@ -4,6 +4,10 @@
|
||||
|
||||
Changes between 0.9.5a and 0.9.6 [xx XXX 2000]
|
||||
|
||||
*) 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
|
||||
|
@ -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…
x
Reference in New Issue
Block a user