1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
require 'openssl'
#OpenSSL::debug = true
include OpenSSL
cacert = X509::Certificate.new(File::read("0cert.pem"))
crl = X509::CRL.new(File::read("0crl.pem"))
user = X509::Certificate.new(File::read("6cert.pem"))
user_key = PKey::RSA.new(File::read("6key-plain.pem"))
responder = X509::Certificate.new(File::read("2cert.pem"))
responder_key = PKey::RSA.new(File::read("2key-plain.pem"))
ee = X509::Certificate.new(File::read("3cert.pem"))
store = X509::Store.new
store.add_cert(cacert)
#store.add_crl(crl)
store.verify_callback = lambda{|ok,ctx|
cert = ctx.current_cert
p [ cert.subject, ctx.error_string ]
return ok
}
##
## requester create a message
##
req = OCSP::Request.new
cid = OCSP::CertificateId.new(ee, cacert)
req.add_certid(cid)
req.add_nonce
req.sign(user, user_key, [user])
req_der = req.to_der
p req_der
##
## send req_der to responder...
##
req = OCSP::Request.new(req_der)
myid = OCSP::CertificateId.new(responder, cacert)
res = nil
if req.verify([], store)
thisupdate = Time.now
nextupdate = Time.now + 3600
basic = OCSP::BasicResponse.new
basic.copy_nonce(req)
req.certid.each{|id|
unless id.cmp_issuer(myid)
# Certificate:
# OCSP::V_CERTSTATUS_GOOD
# OCSP::V_CERTSTATUS_REVOKED
# OCSP::V_CERTSTATUS_UNKNOWN
# OCSP::V_RESPID_NAME
# OCSP::V_RESPID_KEY
basic.add_status(cid, OCSP::V_CERTSTATUS_UNKNOWN, 0, nil,
thisupdate, nextupdate, nil)
next
end
$stdout.printf "serial %d is good certificate? [Y/n]:", id.serial
answer = $stdin.gets
answer.chomp!
if answer.empty? || /^y/i =~ answer
basic.add_status(cid, OCSP::V_CERTSTATUS_GOOD, 0, nil,
thisupdate, nextupdate, nil)
else
# CRLReason:
# OCSP::REVOKED_STATUS_NOSTATUS
# OCSP::REVOKED_STATUS_UNSPECIFIED
# OCSP::REVOKED_STATUS_KEYCOMPROMISE
# OCSP::REVOKED_STATUS_CACOMPROMISE
# OCSP::REVOKED_STATUS_AFFILIATIONCHANGED
# OCSP::REVOKED_STATUS_SUPERSEDED
# OCSP::REVOKED_STATUS_CESSATIONOFOPERATION
# OCSP::REVOKED_STATUS_CERTIFICATEHOLD
# OCSP::REVOKED_STATUS_REMOVEFROMCRL
revoked = Time.now - 3600
basic.add_status(cid, OCSP::V_CERTSTATUS_REVOKED,
OCSP::REVOKED_STATUS_KEYCOMPROMISE, revoked,
thisupdate, nextupdate, nil)
end
}
# Response status:
# OCSP::RESPONSE_STATUS_SUCCESSFUL
# OCSP::RESPONSE_STATUS_MALFORMEDREQUEST
# OCSP::RESPONSE_STATUS_INTERNALERROR
# OCSP::RESPONSE_STATUS_TRYLATER
# OCSP::RESPONSE_STATUS_SIGREQUIRED
# OCSP::RESPONSE_STATUS_UNAUTHORIZED);
basic.sign(responder, responder_key, [responder])
res = OCSP::Response.create(OCSP::RESPONSE_STATUS_SUCCESSFUL, basic)
else
res = OCSP::Response.create(OCSP::RESPONSE_STATUS_UNAUTHORIZED, nil)
end
res_der = res.to_der
p res_der
##
## send req_der to requester...
##
res = OCSP::Response.new(res_der)
p [ res.status, res.status_string ]
if res.status == OCSP::RESPONSE_STATUS_SUCCESSFUL
basic = res.basic
unless basic.verify([], store)
$stderr.puts "invalid OCSP response"
exit 2
end
req.check_nonce(basic)
basic.status.each{|st|
cid, cert_status, reason, revtime, thisupd, nextupd, ext = st
p [ :cid, cid.serial ]
p [ :cert_status, cert_status ]
p [ :thisupd, thisupd ]
p [ :nextupd, nextupd ]
p [ :ext, ext ]
if cert_status == OCSP::V_CERTSTATUS_REVOKED
p [ :resson, reason ]
p [ :revtime, revtime ]
end
}
end
|