$Id: howto-ssleay.html,v 1.9 2002/08/27 06:13:43 sakane Exp $

%Hd: How to use OpenSSL

o OpenSSL とは?
	OpenSSL プロジェクトが提供する暗号関連ライブラリとコマンド群
	以前 Eric Young氏が作っていた SSLeay をプロジェクト化した。
	SSLeay0.9.0b -> OpenSSL0.9.0b だったかな?
	最新は www.openssl.org

	0.9.5 から S/MIMEサポート

	0.9.4 には ASN.1のバグあり。

	0.9.1c は Big Number(BN)のバグがある。BN_RECURSION in crypto/bn/bn.h を
	undefすると平気。

o PKCS#1 ファイルを作る。 ファイル名は privkey.pem modulusは1024ビット % openssl genrsa -out privkey.pem 1024 o PKCS#10 ファイルを作る。 暗号化しない。RSA 1024bits。ファイル名は request.pem % openssl req -new -nodes -newkey rsa:1024 -out request.pem 先に作った PEM形式 PKCS#1ファイル privkey.pem を使う。ハッシュ関数を sha1 に指定。出力形式はPEM % openssl req -new -nodes -sha1 -keyform PEM -key privkey.pem \ -outform PEM -out request.pem X.509 v3 extension を付加する。 ファイルtemplateの [v3_req] セクションに例えば以下の様に書いておくと 追加される。templateは openssl.cnfをコピーして作る。 subjectAltName=email:copy,DNS:shoichi.tanu.org % openssl req -new -nodes -sha1 -keyform PEM -key privkey.pem \ -outform PEM -out request.pem -config template -reqexts v3_req o 自分で署名する。 自分のPKCS#1 RSAPrivateKey ファイルは privkey.pem digest algorithm は SHA1 ファイル名は cert.pem % openssl x509 -req -in request.pem -signkey privkey.pem -sha1 \ -out cert.pem templateファイルの [v3_ca] に書かれたX.509 v3 extensionを使う。 % openssl x509 -req -in request.pem -signkey privkey.pem -sha1 \ -out cert.pem -extfile template -extensions v3_ca o CAのつもりになって署名する。 % openssl x509 -req -in request-mine.pem -sha1 -out cert-mine.pem \ -CA cert-ca.pem -CAkey privkey-ca.pem -CAcreateserial o 証明書を検証する。 検証対象の証明書 cert.pem CAの証明書 CACertFile を指定する場合。 % openssl verify -CAfile CACertFile cert.pem CAの証明書が保存されているディレクトリ ~/.certs を指定する場合。 % openssl verify -CApath ~/.certs cert.pem この時、予め % ln -s ~/.certs/CACertFile ~/.certs/`openssl x509 -noout -hash -in CACertFile`.0 しとく事が重要。 o 証明書から公開鍵を取り出す。 % openssl x509 -in cert-mine.pem -pubkey -noout o S/MIME署名 自分の証明書 cert.pem 自分のPKCS#1 RSAPrivateKeyファイル privkey.pem 署名対象のファイル plain % openssl smime -sign -signer cert.pem -inkey privkey.pem \ -out text.out -in text.in o S/MIME署名検証 検証対象ファイル text.out CAの証明書 CACertFile を指定する場 % openssl smime -verify -CAfile CACertFile -in text.out 検証対象ファイル text.out CAの証明書が保存されているディレクトリ ~/.certs を指定する場合。 % openssl smime -verify -CApath ~/.certs -in text.out CAの証明書は上述の様にハッシュ名で、保存またはリンクされている事が重要。 o S/MIME暗号化 暗号アルゴリズム 3des 相手の証明書 cert.pem % openssl smime -encrypt -des3 -in plain -out encrypted cert.pem o S/MIME復号化 自分の証明書 cert.pem % openssl smime -decrypt -recip cert.pem -inkey privkey.pem -out encrypted -in plain o RSA署名 PKCS#1鍵対のファイル名は privkey.pem % openssl rsautl -sign -inkey privkey.pem -in plain -out encrypted 例えば 1024ビットの鍵だと、118バイト以上のファイルを署名できない。 以下の様に怒られる。 RSA operation error 2194:error:0406C06E:rsa routines:RSA_padding_add_PKCS1_type_1:data too large for key size:/usr/src/secure/lib/libcrypto/../../../crypto/openssl/crypto/rsa/rsa_pk1.c:73: o RSA証明検証 公開鍵のフィアル名は public.pem % openssl rsautl -verify -in encrypted -inkey public.pem -pubin PKCS#1鍵対のファイル名は privkey.pem % openssl rsautl -verify -in encrypted -inkey privkey.pem
http://www-7.cc.columbia.edu/~ariel/ssleay/index.htmlも参考。 dh DH関連。Group 2,5 をサポート。 素数は64ビット(?) bn BigNumber(?)関連ライブラリ バイトオーダーが逆に格納されている。 - 128ビットの疑似乱数を発生させる。 #include #include #include "bn.h" main() { char buf[16]; BIGNUM *a,*b,*c; a=BN_new(); BN_rand(a,128,0,0); memcpy(buf, r->d, size); } - 標準出力にBIGNUMを出力する。 #include #include "bio.h" #include "bn.h" main() { BIGNUM *a,*b,*c; BIO *out; a=BN_new(); out=BIO_new (BIO_s_file()) ; BIO_set_fp(out,stdout,BIO_CLOSE); BN_rand(a,128,0,0); BN_print(out, a); BIO_puts(out,"\n"); } x509 X509形式から公開鍵を拾う X509_get_pubkey() print the contents of X509 structure. int X509_print_fp(FILE *fp, X509 *x) ex. X509_print_fp(stdout, x509); print the contents of X509 CRL structure. int X509_CRL_print_fp(FILE *fp, X509_CRL *x) ex. X509_CRL_print_fp(stdout, x509crl); get issuer name of X509 certificate from X509 structure. X509_NAME *X509_get_issuer_name(X509 *a) ex. X509_get_issuer_name(x509); get subject name of X509 certificate from X509 structure. X509_NAME *X509_get_subject_name(X509 *a) ex. X509_get_subject_name(x509); read X509 certificate from DER format file. X509 *d2i_X509_fp(FILE *fp, X509 **x509) ex. x509 = d2i_X509_fp(fp, NULL); read X509 CRL from DER format file. X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) ex. x509crl = d2i_X509_CRL_fp(fp, NULL); o PEM形式のRSA秘密鍵を読み込む。 read private key from PEM format file. (EVP_PKEY *)PEM_read_PrivateKey(FILE *fp, char **x, pem_password_cb *cb, void *u) #define PEM_read_PrivateKey(fp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read( \ (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb,u) ex. pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); o PEM形式の証明書を読み込む。 read X509 certificate from PEM format file. (X509 *)PEM_read_X509(FILE *fp, char **x, pem_password_cb *cb, void *u) #define PEM_read_X509(fp,x,cb,u) (X509 *)PEM_ASN1_read( \ (char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb,u) ex. x509 = PEM_read_X509(fp, NULL, NULL, NULL); read X509 certificate from buffer. X509 *d2i_X509(X509 **a,unsigned char **pp,long length); ex. u_char *bp = (u_char *)&buf; x509 = d2i_X509(&x509, &bp, buflen); create X509 handler X509 *X509_new(void); ex. x509 = X509_new(); free X509 handler void X509_free(X509 *a); ex. X509_free(x509); ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) X509_EXTENSIONから ASN.1を取り出す。 rsa create RSA handler RSA * RSA_new(void); free RSA handler void RSA_free(RSA *rsa); RSA public encryption int RSA_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding); RSA private decryption int RSA_private_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding); get RSA modulus size. int RSA_size(RSA *rsa); padding と Encryption schemes の関係 RSA_PKCS1_PADDING PKCS#1 RSAES-PKCS1-v1_5 RSA_SSLV23_PADDING RSA_NO_PADDING RSA_PKCS1_OAEP_PADDING PKCS#1 RSAES-OAEP asn1 ASN.1関連ライブラリ int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a) ASN.1オブジェクト名を bio へ出力する。 最大80文字 ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **a, unsigned char **pp, long length) ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) ASN1_OBJECT_free(obj); nid = OBJ_obj2nid(obj); apps.c: ? X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, char *field, int type, unsigned char *bytes, int len) field = "C", "CN", ... if (!X509_NAME_add_entry_by_txt(subj,type, MBSTRING_ASC, (unsigned char *) v->value,-1,-1,0)) return 0; ? ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) "C"や"CN"をNIDに変換。 bio 入出力関連ライブラリ create BIO handler. BIO *BIO_new(BIO_METHOD *method) method is the one of following: BIO_s_file_internal(void); BIO_s_file(void ); BIO_s_mem(void); BUF_MEM BIO_s_socket(void); BIO_s_connect(void); BIO_s_accept(void); BIO_s_fd(void); BIO_s_log(void); BIO_s_bio(void); BIO_s_null(void); BIO_f_null(void); BIO_f_buffer(void); BIO_F_BUFFER_CTX BIO_f_nbio_test(void); ex. bio = BIO_new(BIO_s_mem()); bio = BIO_s_mem() はバッファハンドリングお任せ。 read the buffer with specified length. int BIO_read(BIO *b, void *out, int outl) write data into the buffer with specified length. int BIO_write(BIO *b, const char *in, int inl) ex. i = BIO_write(bio, buf, buflen); set the pointer of outer buffer into the bio buffer. #define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm) ex. BIO_set_mem_buf(bio, buf, buflen); get the pointer to the buffer and its length. ex. len = BIO_get_mem_data(bio, &bp); free BIO handler. int BIO_free(BIO *a) ex. BIO_free(bio); sk crypto/stack/safestack.h で定義されている。 STACK_OF(type) IMPLEMENT_STACK_OF(type) sk_##type##_foge() ex. sk_X509_EXTENSION_value() ↓な感じ type *sk_##type##_value(const STACK_OF(type) *sk,int n) \ { return (type *)sk_value((STACK *)sk,n); } \