ラベル PKI の投稿を表示しています。 すべての投稿を表示
ラベル PKI の投稿を表示しています。 すべての投稿を表示

2013/08/12

golang certificate ssl handshake

2013/08/14 追記
Go界のジェフ・ベゾスが勝手にウンコードを添削してくれたよ!! みんな、こっち見てね!

ヒャッハー、証明書好きのオレ様が帰ってきたぜ!!!というわけで遅延証明書よりも在留証明書よりも公開鍵証明書を愛する私が Go を使ってサーバから証明書をゲットするその日がやってきました。Go には crypto/tls という素敵パッケージもあるので何の心配もありません。Config としてサーバ認証を真面目にしない InsecureSkipVerify を true としてあげればどんな IP address, port のペアに対してだって証明書を取ってくることが可能なのです。実行するとこんな:
$ go run get_cert.go www.google.com
i=0
[[{[2 5 4 6] US}] [{[2 5 4 10] Google Inc}] [{[2 5 4 3] Google Internet Authority}]]
2013-07-31 11:40:49 +0000 UTC
2013-10-31 23:59:59 +0000 UTC
[[{[2 5 4 6] US}] [{[2 5 4 10] Google Inc}] [{[2 5 4 7] Mountain View}] [{[2 5 4 8] California}] [{[2 5 4 3] www.google.com}]]
i=1
[[{[2 5 4 6] US}] [{[2 5 4 10] Equifax}] [{[2 5 4 11] Equifax Secure Certificate Authority}]]
2012-12-12 15:58:50 +0000 UTC
2013-12-31 15:58:50 +0000 UTC
[[{[2 5 4 6] US}] [{[2 5 4 10] Google Inc}] [{[2 5 4 3] Google Internet Authority}]]
OpenSSL みたいな pretty な感じに出してくれるのはとりあえず見つからなかったけど頑張れば自分で書けるぜ!!
package main

import (
        "crypto/tls"
        "crypto/x509"
        "fmt"
        "log"
        "os"
)

func main() {
        if len(os.Args) < 1 {
                log.Fatal("You must input a hostname")
        }
        peerCertificates, err := GetCert(os.Args[1])
        if err == nil {
                for i, Cert := range peerCertificates {
                        fmt.Printf("i=%d\n", i)
                        fmt.Println(Cert.Issuer.ToRDNSequence())
                        fmt.Println(Cert.NotBefore)
                        fmt.Println(Cert.NotAfter)
                        fmt.Println(Cert.Subject.ToRDNSequence())
                }
        } else {
                log.Fatal(err)
        }
}

func GetCert(host string) ([]*x509.Certificate, error) {
        config := &tls.Config{InsecureSkipVerify: true}
        conn, err := tls.Dial("tcp", host+":443", config)
        var peerCertificates []*x509.Certificate
        if err == nil {
                connectionState := conn.ConnectionState()
                peerCertificates = connectionState.PeerCertificates
        }
        return peerCertificates, err
}
ポートは決め打ちだぜ!!

2010/10/05

cryptoapi aia windows-98

cryptoapi というのはここでは Windows API の暗号のやつを想定
AIA は Authority Information Access の略
Authority Information Access は X.509 などの機能拡張
X.509 は公開鍵証明書の規格の名前
で Windows 98 は Microsoft の OS の名前

で、やっぱ AIA ですよね、何それ? っていうの
http://www.ipa.go.jp/security/rfc/RFC5280-04JA.html#042201 見ると
その証明書の認証局の証明書が入ったりするみたいです。

で、ここで我らが Microsoft さんの登場です。
いつも知らないところで色々してくれてる Microsoft さん。
CryptoAPI で証明書を検証するときにも AIA をちゃんと見てくれて
手元に指されてる証明書が無かったら取ってきてくれたりするんです。

えー、まじでー

っていうのを検索した結果の「暗号と PKI の基本」には書いてあります

にしても「RFC 5280」にしても「暗号と PKI の基本」にしても
長い
引用しようと思ったけど必要なとこ含ませると長くなっちゃって
そんなダラダラ引用しても仕方ないから引用しませんでした
なんかもーこっとさっくり言えないもんすかねぇ

で、Windows 98 ですよ、検索語句にも含めた
Windows 98 でもそうなのかどうか? が良く分からず
検索自体は空振りに終わってしまいました
実機検証でもできたらいいんですが...

Windows 98 ってどうやったらいま動かせるの??
CD はあるんですが boot disk が見当たらず
FreeDOS と仮想化技術で何とかならないのかなぁと思うんですが
面倒ですね、Windows 98 までそこまでするか??

いかん、Microsoft の話してるのに愚痴が多くなってしまった

2010/04/23

gnutls python

悪ノリも大概にしなさいという気がしないでもないですが
どうせならと思って gnutls も使ってみようと
Python であれば python-gnutls というのがあります
easy_install でも pip でも使えば入ってしまいます

example とかも揃っているので良く分かってなくても使えてしまいましたが
from gnutls import crypto

x509 = crypto.X509Certificate(open("google.crt").read())

print "version: %d" % x509.version
print "serial number: %s" % x509.serial_number
print "issuer: %s" % x509.issuer.title()
print "not before: %s" % time.ctime(x509.activation_time)
print "not after: %s" % time.ctime(x509.expiration_time)
print "subject: %s" % x509.subject.title()
とか
import socket
import time

from gnutls import connection

cred = connection.X509Credentials()

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
session = connection.ClientSession(sock, cred)

session.connect(('www.google.com', 443))
session.handshake()
x509 = session.peer_certificate
session.bye()
session.close()

print "version: %d" % x509.version
print "serial number: %s" % x509.serial_number
print "issuer: %s" % x509.issuer.title()
print "not before: %s" % time.ctime(x509.activation_time)
print "not after: %s" % time.ctime(x509.expiration_time)
print "subject: %s" % x509.subject.title()
とかすると
version: 3
serial number: 205024093581220934167709006090448199471
issuer: C=Za,O=Thawte Consulting (Pty) Ltd.,Cn=Thawte Sgc Ca
not before: Fri Dec 18 09:00:00 2009
not after: Mon Dec 19 08:59:59 2011
subject: C=Us,St=California,L=Mountain View,O=Google Inc,Cn=Www.Google.Com
こんなのが出ました

gnutls.constants.X509_FMT_DER とかあるので DER も読めたり
gnutls.library.functions ってのがあるんでガリガリ書いたり
できるのかな? 試していません

とりあえず証明書は読めました

2010/04/20

sslsocketfactory session getdefault

Jython で Java を使って SSL 張って証明書を取ろうとしました

色々ググったりして SSLSocketFactory ってのがあるということで
java.net パッケージの仕組み
を見てふんふんとする
で、socket を作って getSession したらそこに getPeerCertificates という method が!
In [63]: soc = factory.createSocket('www.google.com', 443)

In [1]: from javax.net.ssl import *

In [2]: sock = factory.createSocket('www.google.com', 443)

In [3]: session = sock.getSession()

In [4]: certs = session.getPeerCertificates()
---------------------------------------------------------------------------
SSLPeerUnverifiedException Traceback (most recent call last)

/tmp/<ipython console> in <module>()

SSLPeerUnverifiedException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

In [5]:
うぎゃぁ!!

何か足りないのみたいなのでググり直すと
HTTPS通信にはまる - TNET日々のメモ
そうですよね、handshake してませんでした

ということで
import sys
from javax.net.ssl import SSLSocketFactory

host = "www.google.com"
port = 443

factory = SSLSocketFactory.getDefault()
sock = factory.createSocket(host, port)
sock.startHandshake()
session = sock.getSession()
certs = session.getPeerCertificates()

for c in certs:
print '-----BEGIN CERTIFICATE-----'
print c.getEncoded().tostring().encode('base64').rstrip()
print '-----END CERTIFICATE-----'
Certificate を PEM で出したかったんですが
DER を array で取り出す方法しか分からなかったので
Jython str にして encode してしまいました
てゆーか array なんてあったんだー使ったことないよー

でどうなるかというと
$ jython get_certs.jy www.google.com
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQG
EwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhh
d3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0xMTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApH
b29nbGUgSW5jMRcwFQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jNgtXj9xVo
RaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L05vuuWciKh0R73mkszeK
9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAMBgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0w
K6ApoCeGJWh0dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYI
KwYBBQUHAwEGCCsGAQUFBwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzAB
hhZodHRwOi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0ZS5j
b20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUFAAOBgQCfQ89bxFAp
sb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5u2ONgJd8IyAPkU0Wueru9G2Jysa9
zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqA
ibAxWEEHXw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEXMBUGA1UE
ChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlm
aWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAwMDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYD
VQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMN
VGhhd3RlIFNHQyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGh
PwtxPKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g5/OIty0y
3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo3nWhLHpo39XKHIdYYBkC
AwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEE
BAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCow
KDAmoCSgIoYgaHR0cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAk
MCIGCCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUFBwMB
BggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEBBQUAA4GBAFWsY+re
od3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTcq3J5Lwa/q4FwxKjt6lM07e8eU9kG
x1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTRbcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXW
rOU/VG+WHgWv
-----END CERTIFICATE-----
$
ありゃ、1行が76文字に...

まぁいいや、Java で証明書が取れました

InputStream 文字列

色々ググっていたら
Java(TM) PKI API プログラマーズガイド
ってのを見付けました
こりゃいいや、これに違いない

で、先ず証明書読みたいと思いまして読み進めると
java.security.cert.CertificateFactory
を使うと良いらしく、サンプルも
Java 暗号化アーキテクチャー (JCA)
に書いてありました
FileInputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis);

CertificateFactory cf = CertificateFactory.getInstance("X.509");

while (bis.available() > 0) {
Certificate cert = cf.generateCertificate(bis);
System.out.println(cert.toString());
}


でも file を Java で読みたくないなぁ
でも Jython で file 開いた後どうするんだろう
中身を str にしたら何とかならないかな
つわけでググってみると
String文字列をInputStreamに変換する方法 - Java入門
そうそう、こういうの

というわけで簡単に証明書の中身を出してみました
from java.security.cert import CertificateFactory
from java.io import ByteArrayInputStream

pem_file = open("google.pem", "r")
cf = CertificateFactory.getInstance("X.509")
pem_stream = ByteArrayInputStream(pem_file.read())
x509 = cf.generateCertificate(pem_stream)

print x509.version
print x509.sigAlgName
print x509.issuerDN
print x509.notBefore
print x509.notAfter
print x509.subjectDN
これがこうなります
$ jython read_cert.jy
3
SHA1withRSA
CN=Thawte SGC CA, O=Thawte Consulting (Pty) Ltd., C=ZA
Fri Dec 18 09:00:00 JST 2009
Mon Dec 19 08:59:59 JST 2011
CN=www.google.com, O=Google Inc, L=Mountain View, ST=California, C=US
$

Python で開いた file をそのまま InputStream? にする方法もある気がする
今度調べよう

2010/04/14

"GetOcspSignerCertificate"

失効されてるはずなのに OCSP が教えてくれないな〜
Windows でそんなことが起きた場合にはイベント ビューアーを見ましょう
Windows 7 であればイベント ビューアーを開くを参考

[アプリケーションとサービス ログ] -> [Microsoft] -> [Windows] -> [CAPI2]
と進みます
この CAPI2 は CryptoAPI 2 の略で、1 は XP とか 2003 までのものなのかな?
Vista/2008 移行の色々機能が強化された CryptoAPI が CAPI2 です

デフォルトだとログが無効化されているので右の方にある [ログを有効化] を押せば
SSL なページを見にいったときの証明書の検証のログなどをガシガシ保存してくれます

例えばエラーが出てるところを見て
GetOcspSignerCertificate なんて書いてあったとしますと
検索することによって
Windows Vista での PKI に関する問題のトラブルシューティング
というページがひっかかりますので探しますと

OCSP 応答には署名が必要であり、OCSP 署名者の証明書には OCSP 署名 EKU が含まれている必要があります。この EKU がないと、エラーが発生します。このエラーは、"CertRejectedRevocationInfo" イベントの操作 "GetOCSPSignerCertificate" で示されます。OCSP 署名者の証明書の内容でその他のエラーが発生した場合も、同じ操作がログに記録されます。このようなエラーには、次のものがあります。

  • 期間が無効な証明書

  • CDP 拡張機能または OCSP URL は含まれていても "Revocation_No_Check" 拡張機能が含まれていない証明書

これらのエラーの場合、CAPI2 では、OCSP 署名者の証明書に関する情報もログに記録されます。

ほぉほぉ

Revocation_No_Check というのは RFC2560 の 4.2.2.2.1 に
id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 } と記載が
1.3.6.1.5.5.7.48.1.5 ですね
OCSP はオンラインでやりとりをするので MITM などの対応をしなくてはいけません
OCSP Responder が信頼できるかどうかの判断はとても大切です

ちなみに OpenSSL の場合 man x509v3_config を見れば
   OCSP No Check
The OCSP No Check extension is a string extension but its value is ignored.

Example:

noCheck = ignored
という記述が見付けられます

やぁ、Google って便利ですね

2010/02/05

erlang ssl_esock

HTTPS サーバーから証明書を取ってこようシリーズ
今回は Erlang です

Erlang の SSL な module はこちら
Erlang -- SSL Reference Manual
ざっと見ると getpeercert という関数があるのでこれっぽいです

左のコラムに ssl と ssl_new というのがありますが、これは
以前は SSL 関連でも全て OpenSSL を利用していたようで
connection を張ろうとしたりすると ssl_esock という subprocess が立ち
そいつに色々と仕事を任せていたようです
でも Erlang 的にはそこに C が入ってしまうので嬉しくありません

そこで cryptographic primitive な部分だけ OpenSSL を使って
connection の部分なんかを Erlang で実装したのが ssl_new のようです
cryptographic primitive は crypto って application を使います

で、application とか良く分かってないんですが
とりあえず start とかしといたらいいんでしょ、というのが次
-module(get_cert).
-compile(export_all).

get_cert(Host) ->
application:start(crypto),
application:start(ssl),
{ok, Sock} = ssl:connect(Host, 443, [{ssl_imp, new}]),
{ok, Der} = ssl:peercert(Sock),
{ok, Cert} = public_key:pkix_decode_cert(Der, otp),
ssl:close(Sock),
application:stop(ssl),
application:stop(crypto),
Cert.
ssl:connect の option に ssl_new を使うと伝え
ssl:peercert で証明書を DER で取り
public_key:pkix_decode_cert でそれを parse しています
otp ってあるのは parse の形式で、あと plain があります
それぞれ
-include_lib("public_key/include/public_key.hrl").
-include_lib("public_key/include/OTP-PUB-KEY.hrl").
的なことをしておけば読み易いです
かんたんなことしかしていませんね

で、動かしてみると
$ erl
Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4 (abort with ^G)
1> get_cert:get_cert("blogger.com").

=INFO REPORT==== 15-Feb-2010::01:34:14 ===
application: crypto
exited: stopped
type: temporary

=INFO REPORT==== 15-Feb-2010::01:34:14 ===
application: ssl
exited: stopped
type: temporary
{'OTPCertificate',
{'OTPTBSCertificate',v3,134060097170805708820381,
{'SignatureAlgorithm',{1,2,840,113549,1,1,5},'NULL'},
{rdnSequence,
[[{'AttributeTypeAndValue',{2,5,4,6},"US"}],
[{'AttributeTypeAndValue',
{2,5,4,10},
{printableString,"Google Inc"}}],
[{'AttributeTypeAndValue',
{2,5,4,3},
{printableString,"Google Internet Authority"}}]]},
{'Validity',
{utcTime,"091222015844Z"},
{utcTime,"101222020844Z"}},
{rdnSequence,
[[{'AttributeTypeAndValue',{2,5,4,6},"US"}],
[{'AttributeTypeAndValue',
{2,5,4,8},
{printableString,"California"}}],
[{'AttributeTypeAndValue',
{2,5,4,7},
{printableString,"Mountain View"}}],
[{'AttributeTypeAndValue',
{2,5,4,10},
{printableString,"Google Inc"}}],
[{'AttributeTypeAndValue',
{2,5,4,3},
{teletexString,"*.blogger.com"}}]]},
(あと長いんで略)
こんな感じで X.509 を parse してくれてます

ちなみに public_key の Reference は
Erlang -- public_key
にあって
例えば pem_to_der ってのを使えば PEM の PATH 与えて
DER で返してくれるなんてのも分かります

2010/01/25

pdf 署名

PDF に署名したいなーって思いました
ググりました

Adobe Acrobat 使えばいいみたいなんですが
手元にあるのが弱いバージョンだからなのか
Reader と上手く連携してないからなのか
何だか良く分かりません

っていうか Linux とかでしたいじゃん

で、これですね
MOONGIFT: » PDFに署名をする「PortableSigner」:オープンソースを毎日紹介
Java で書かれてるようなので Linux でもいけそうだ!
と言いながらとりあえず Windows XP で試してみたんですが
インストールして Readme を参照して JCE というのを入れてみたら
しっかり署名することができました
簡単!
まぁ、きっと Acrobat を使うともっと凄いこと色々できるんだろうなぁ

で、Acrobat で開くと
「文書の証明の完全性が不明です。作成者が検証できませんでした。」
って出ます。
これはルート証明書から署名した証明書まで辿れなかったってことだろう
と思ったんでちょっと仕組みを調べてみました。

といっても、メニューの「文書」に「信頼済み証明書」ってのがあって
それ開いて表示を「証明書」にすれば良かっただけなんですが。
で、そこには Adobe Root CA ってのしかありません。
ん〜? と思って他のも調べてみると Reader の 8 までは Adobe Root CA のみ
9 になると色々と第三者機関の証明書も入っていました。

全ての信頼の起点はこれなの? と思いもう少し調べてみると
Windows であれば
[編集] -> [環境設定] -> [セキュリティ] -> [詳細環境設定]
と進んで [Windows 統合] ってところで
片っ端からチェックすればいいみたい。
Windows で信頼されているルートを Reader でも信頼することになります。

んでは、信頼済みな証明書ってのは何のことなの? って思ったので
更にしつこくググってみたら
Adobe - Certified Document Services (CDS)
に辿り着きました。

なるほど、Microsoft の場合は
Microsoft Root Certificate Program
Firefox の場合は
Mozilla CA Certificate Store Information
で採用されていないといけないわけですが
Adobe Reader に関してもそういうのがあるってことですね。
でも Adobe の少なくないの?

PDF の方が色々用途があったり署名が頻繁だからなのか
商品ラインナップも個人用とか法人用とかあったりして
署名できる回数も決まってたりで複雑そうでした。
タイムスタンプとかその辺良く分かってないんですが。
同じ Adobe でも Air 用の Code Signing とかとは勝手が違うみたい。
ビジネスとか法律の香がしてきました。