certificate-transparency-client 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|