certificate-transparency-client 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/certificate-transparency-client.gemspec +2 -1
- data/lib/certificate-transparency/client.rb +108 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d6a56b3273a0429713b312948b1d4d6aa6fcf58
|
4
|
+
data.tar.gz: 7ea05b65e5b80d272f358d8e6b54220838df10fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a73f1d0a7f17adb86d52a3f300ec67b254521622fd14fba920803748ee613e6fa3c297e21d240042ad870981827c8000483e75069078c08ed888e2090904f076
|
7
|
+
data.tar.gz: 619c902a80cc5253b862840e80a36531c52f58ad39d5d2926a96d251c488081feaead33021d5f7cfa27ffe33d1527779031d079872be2a24ee99f2667f77c95d
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.required_ruby_version = ">= 1.9.3"
|
24
24
|
|
25
|
-
s.add_runtime_dependency 'certificate-transparency', '~> 0.
|
25
|
+
s.add_runtime_dependency 'certificate-transparency', '~> 0.4'
|
26
26
|
|
27
27
|
s.add_development_dependency 'bundler'
|
28
28
|
s.add_development_dependency 'github-release'
|
@@ -33,5 +33,6 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_development_dependency 'rb-inotify', '~> 0.9'
|
34
34
|
s.add_development_dependency 'redcarpet'
|
35
35
|
s.add_development_dependency 'rspec'
|
36
|
+
s.add_development_dependency 'webmock'
|
36
37
|
s.add_development_dependency 'yard'
|
37
38
|
end
|
@@ -1,9 +1,36 @@
|
|
1
1
|
require 'certificate-transparency'
|
2
2
|
require 'openssl'
|
3
|
+
require 'uri'
|
3
4
|
|
4
5
|
# Interact with a Certificate Transparency server.
|
5
6
|
#
|
6
7
|
class CertificateTransparency::Client
|
8
|
+
# Base class for all errors from CT::Client.
|
9
|
+
#
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
# Indicates an error in making a HTTP request.
|
13
|
+
#
|
14
|
+
class HTTPError < Error; end
|
15
|
+
|
16
|
+
# The public key of the log, as specified in the constructor.
|
17
|
+
#
|
18
|
+
# @return [OpenSSL::PKey]
|
19
|
+
#
|
20
|
+
attr_reader :public_key
|
21
|
+
|
22
|
+
# Create thyself a new CT::Client.
|
23
|
+
#
|
24
|
+
# @param url [String] the "base" URL to the CT log, without any
|
25
|
+
# `/ct/v1` bits in it.
|
26
|
+
#
|
27
|
+
# @param opts [Hash] any options you'd like to pass.
|
28
|
+
#
|
29
|
+
# @option public_key [String] either the "raw" bytes of a log's public
|
30
|
+
# key, or the base64-encoded form of same.
|
31
|
+
#
|
32
|
+
# @return [CT::Client]
|
33
|
+
#
|
7
34
|
def initialize(url, opts = {})
|
8
35
|
unless opts.is_a? Hash
|
9
36
|
raise ArgumentError,
|
@@ -12,7 +39,7 @@ class CertificateTransparency::Client
|
|
12
39
|
|
13
40
|
if opts[:public_key]
|
14
41
|
begin
|
15
|
-
@
|
42
|
+
@public_key = if opts[:public_key].valid_encoding? && opts[:public_key] =~ /^[A-Za-z0-9+\/]+=*$/
|
16
43
|
OpenSSL::PKey::EC.new(opts[:public_key].unpack("m").first)
|
17
44
|
else
|
18
45
|
OpenSSL::PKey::EC.new(opts[:public_key])
|
@@ -25,4 +52,84 @@ class CertificateTransparency::Client
|
|
25
52
|
|
26
53
|
@url = URI(url)
|
27
54
|
end
|
55
|
+
|
56
|
+
# Retrieve the current Signed Tree Head from the log.
|
57
|
+
#
|
58
|
+
# @return [CT::SignedTreeHead]
|
59
|
+
#
|
60
|
+
# @raise [CT::Client::HTTPError] if something goes wrong with the HTTP
|
61
|
+
# request.
|
62
|
+
#
|
63
|
+
def get_sth
|
64
|
+
CT::SignedTreeHead.from_json(make_request("get-sth"))
|
65
|
+
end
|
66
|
+
|
67
|
+
# Retrieve one or more entries from the log.
|
68
|
+
#
|
69
|
+
# @param first [Integer] the 0-based index of the first entry in the log
|
70
|
+
# that you wish to retrieve.
|
71
|
+
#
|
72
|
+
# @param last [Integer] the 0-base indexd of the last entry in the log
|
73
|
+
# that you wish to retrieve. Note that you may not get as many entries
|
74
|
+
# as you requested, due to limits in the response size that are imposed
|
75
|
+
# by many log servers.
|
76
|
+
#
|
77
|
+
# If `last` is not specified, this method will attempt to retrieve as
|
78
|
+
# many entries as the log is willing and able to hand over.
|
79
|
+
#
|
80
|
+
# @return [Array<CT::LogEntry>]
|
81
|
+
#
|
82
|
+
# @raise [CT::Client::HTTPError] if something goes wrong with the HTTP
|
83
|
+
# request.
|
84
|
+
#
|
85
|
+
def get_entries(first, last = nil)
|
86
|
+
last ||= get_sth.tree_size - 1
|
87
|
+
|
88
|
+
entries_json = make_request("get-entries", :start => first, :end => last)
|
89
|
+
JSON.parse(entries_json)["entries"].map do |entry|
|
90
|
+
CT::LogEntry.from_json(entry.to_json)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Make a request to the log server.
|
97
|
+
#
|
98
|
+
# @param op [String] the bit after `/ct/v1/` in the URL path.
|
99
|
+
#
|
100
|
+
# @param params [Hash<#to_s, #to_s>] any query params you wish to send
|
101
|
+
# off with the request.
|
102
|
+
#
|
103
|
+
# @return [String]
|
104
|
+
#
|
105
|
+
# @raise [CT:Client::HTTPError] if anything goes spectacularly wrong.
|
106
|
+
#
|
107
|
+
def make_request(op, params = nil)
|
108
|
+
resp = Net::HTTP.get_response(url(op, params))
|
109
|
+
|
110
|
+
if resp.code != "200"
|
111
|
+
raise CT::Client::HTTPError,
|
112
|
+
"Failed to #{op}: got HTTP #{resp.code}"
|
113
|
+
end
|
114
|
+
|
115
|
+
if resp["Content-Type"] != "application/json"
|
116
|
+
raise CT::Client::HTTPError,
|
117
|
+
"Failed to #{op}: received incorrect Content-Type (#{resp["Content-Type"]})"
|
118
|
+
end
|
119
|
+
|
120
|
+
resp.body
|
121
|
+
end
|
122
|
+
|
123
|
+
# Generate a URL for the given `op` and `params`.
|
124
|
+
#
|
125
|
+
# @see {#make_request}.
|
126
|
+
#
|
127
|
+
def url(op, params = nil)
|
128
|
+
@url.dup.tap do |url|
|
129
|
+
url.path += "/ct/v1/#{op}"
|
130
|
+
if params
|
131
|
+
url.query = params.map { |k,v| "#{k}=#{v}" }.join("&")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
28
135
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: certificate-transparency-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Palmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: certificate-transparency
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.4'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.4'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,6 +142,20 @@ dependencies:
|
|
142
142
|
- - ">="
|
143
143
|
- !ruby/object:Gem::Version
|
144
144
|
version: '0'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: webmock
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
145
159
|
- !ruby/object:Gem::Dependency
|
146
160
|
name: yard
|
147
161
|
requirement: !ruby/object:Gem::Requirement
|