bnet-authenticator 0.1.3 → 0.1.4
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/lib/bnet/authenticator.rb +3 -83
- data/lib/bnet/authenticator/version.rb +1 -1
- data/lib/bnet/authenticator_helper.rb +95 -0
- data/lib/bnet/command.rb +1 -1
- data/lib/bnet/constants.rb +31 -0
- data/lib/bnet/errors.rb +6 -0
- data/test/test_battlenet_authenticator.rb +6 -6
- metadata +4 -3
- data/lib/bnet/authenticator/constants.rb +0 -35
- data/lib/bnet/authenticator/errors.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82d4b4048774174d05fac51442d1fa7314c0cff7
|
4
|
+
data.tar.gz: 79a85eaf15072ae7548b87eabbc344d5161e6fef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d2ac8f76a5e66e123f93ff4b44d4940222eb6eaa6d95c390c5944d4c95420661738d7e65ce87e042e2092b1348d0fb8c2535ca0b42f0af7549f90bb887904b2
|
7
|
+
data.tar.gz: 2844c2afa341884aec85670c6c1d814381bf264d4f87c8b22b867fc756eae790b5b36a4ae286ec2f0f5517ed7bab3785ce51731ea23330830edc1e10c887a194
|
data/lib/bnet/authenticator.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
require 'bnet/
|
2
|
-
require 'bnet/
|
3
|
-
require 'bnet/authenticator/constants'
|
4
|
-
require 'digest/sha1'
|
5
|
-
require 'digest/hmac'
|
6
|
-
require 'net/http'
|
1
|
+
require 'bnet/errors'
|
2
|
+
require 'bnet/authenticator_helper'
|
7
3
|
|
8
4
|
module Bnet
|
9
5
|
|
10
6
|
# The Battle.net authenticator
|
11
7
|
class Authenticator
|
8
|
+
include AuthenticatorHelper
|
12
9
|
|
13
10
|
# @!attribute [r] serial
|
14
11
|
# @return [String] serial
|
@@ -137,83 +134,6 @@ module Bnet
|
|
137
134
|
to_hash.to_s
|
138
135
|
end
|
139
136
|
|
140
|
-
class << self
|
141
|
-
def is_valid_serial?(serial)
|
142
|
-
normalized_serial = normalize_serial(serial)
|
143
|
-
normalized_serial =~ Regexp.new("^(#{AUTHENTICATOR_HOSTS.keys.join('|')})\\d{12}$") && is_valid_region?(extract_region(normalized_serial))
|
144
|
-
end
|
145
|
-
|
146
|
-
def normalize_serial(serial)
|
147
|
-
serial.upcase.gsub(/-/, '')
|
148
|
-
end
|
149
|
-
|
150
|
-
def extract_region(serial)
|
151
|
-
serial[0, 2].upcase.to_sym
|
152
|
-
end
|
153
|
-
|
154
|
-
def prettify_serial(serial)
|
155
|
-
"#{serial[0, 2]}-" + serial[2, 12].scan(/.{4}/).join('-')
|
156
|
-
end
|
157
|
-
|
158
|
-
def is_valid_secret?(secret)
|
159
|
-
secret =~ /[0-9a-f]{40}/i
|
160
|
-
end
|
161
|
-
|
162
|
-
def is_valid_region?(region)
|
163
|
-
AUTHENTICATOR_HOSTS.has_key? region
|
164
|
-
end
|
165
|
-
|
166
|
-
def is_valid_restorecode?(restorecode)
|
167
|
-
restorecode =~ /[0-9A-Z]{10}/
|
168
|
-
end
|
169
|
-
|
170
|
-
def encode_restorecode(bin)
|
171
|
-
bin.bytes.map do |v|
|
172
|
-
RESTORECODE_MAP[v & 0x1f]
|
173
|
-
end.as_bytes_to_bin
|
174
|
-
end
|
175
|
-
|
176
|
-
def decode_restorecode(str)
|
177
|
-
str.bytes.map do |c|
|
178
|
-
RESTORECODE_MAP_INVERSE[c]
|
179
|
-
end.as_bytes_to_bin
|
180
|
-
end
|
181
|
-
|
182
|
-
def create_one_time_pad(length)
|
183
|
-
(0..1.0/0.0).reduce('') do |memo, i|
|
184
|
-
break memo if memo.length >= length
|
185
|
-
memo << Digest::SHA1.digest(rand().to_s)
|
186
|
-
end[0, length]
|
187
|
-
end
|
188
|
-
|
189
|
-
def decrypt_response(text, key)
|
190
|
-
text.bytes.zip(key.bytes).reduce('') do |memo, pair|
|
191
|
-
memo + (pair[0] ^ pair[1]).chr
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def rsa_encrypted(integer)
|
196
|
-
(integer ** RSA_KEY % RSA_MOD).to_bin
|
197
|
-
end
|
198
|
-
|
199
|
-
def request_for(label, region, path, body = nil)
|
200
|
-
request = body.nil? ? Net::HTTP::Get.new(path) : Net::HTTP::Post.new(path)
|
201
|
-
request.content_type = 'application/octet-stream'
|
202
|
-
request.body = body unless body.nil?
|
203
|
-
|
204
|
-
response = Net::HTTP.new(AUTHENTICATOR_HOSTS[region]).start do |http|
|
205
|
-
http.request request
|
206
|
-
end
|
207
|
-
|
208
|
-
if response.code.to_i != 200
|
209
|
-
raise RequestFailedError.new("Error requesting #{label}: #{response.code}")
|
210
|
-
end
|
211
|
-
|
212
|
-
response.body
|
213
|
-
end
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
137
|
end
|
218
138
|
|
219
139
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'bnet/support'
|
2
|
+
require 'bnet/constants'
|
3
|
+
require 'digest/sha1'
|
4
|
+
require 'digest/hmac'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
module Bnet
|
8
|
+
|
9
|
+
module AuthenticatorHelper
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
|
13
|
+
class << base
|
14
|
+
|
15
|
+
def is_valid_serial?(serial)
|
16
|
+
normalized_serial = normalize_serial(serial)
|
17
|
+
normalized_serial =~ Regexp.new("^(#{AUTHENTICATOR_HOSTS.keys.join('|')})\\d{12}$") && is_valid_region?(extract_region(normalized_serial))
|
18
|
+
end
|
19
|
+
|
20
|
+
def normalize_serial(serial)
|
21
|
+
serial.upcase.gsub(/-/, '')
|
22
|
+
end
|
23
|
+
|
24
|
+
def extract_region(serial)
|
25
|
+
serial[0, 2].upcase.to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
def prettify_serial(serial)
|
29
|
+
"#{serial[0, 2]}-" + serial[2, 12].scan(/.{4}/).join('-')
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_valid_secret?(secret)
|
33
|
+
secret =~ /[0-9a-f]{40}/i
|
34
|
+
end
|
35
|
+
|
36
|
+
def is_valid_region?(region)
|
37
|
+
AUTHENTICATOR_HOSTS.has_key? region
|
38
|
+
end
|
39
|
+
|
40
|
+
def is_valid_restorecode?(restorecode)
|
41
|
+
restorecode =~ /[0-9A-Z]{10}/
|
42
|
+
end
|
43
|
+
|
44
|
+
def encode_restorecode(bin)
|
45
|
+
bin.bytes.map do |v|
|
46
|
+
RESTORECODE_MAP[v & 0x1f]
|
47
|
+
end.as_bytes_to_bin
|
48
|
+
end
|
49
|
+
|
50
|
+
def decode_restorecode(str)
|
51
|
+
str.bytes.map do |c|
|
52
|
+
RESTORECODE_MAP_INVERSE[c]
|
53
|
+
end.as_bytes_to_bin
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_one_time_pad(length)
|
57
|
+
(0..1.0/0.0).reduce('') do |memo, i|
|
58
|
+
break memo if memo.length >= length
|
59
|
+
memo << Digest::SHA1.digest(rand().to_s)
|
60
|
+
end[0, length]
|
61
|
+
end
|
62
|
+
|
63
|
+
def decrypt_response(text, key)
|
64
|
+
text.bytes.zip(key.bytes).reduce('') do |memo, pair|
|
65
|
+
memo + (pair[0] ^ pair[1]).chr
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def rsa_encrypted(integer)
|
70
|
+
(integer ** RSA_KEY % RSA_MOD).to_bin
|
71
|
+
end
|
72
|
+
|
73
|
+
def request_for(label, region, path, body = nil)
|
74
|
+
request = body.nil? ? Net::HTTP::Get.new(path) : Net::HTTP::Post.new(path)
|
75
|
+
request.content_type = 'application/octet-stream'
|
76
|
+
request.body = body unless body.nil?
|
77
|
+
|
78
|
+
response = Net::HTTP.new(AUTHENTICATOR_HOSTS[region]).start do |http|
|
79
|
+
http.request request
|
80
|
+
end
|
81
|
+
|
82
|
+
if response.code.to_i != 200
|
83
|
+
raise RequestFailedError.new("Error requesting #{label}: #{response.code}")
|
84
|
+
end
|
85
|
+
|
86
|
+
response.body
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
data/lib/bnet/command.rb
CHANGED
@@ -42,7 +42,7 @@ module Bnet
|
|
42
42
|
|
43
43
|
begin
|
44
44
|
run
|
45
|
-
rescue Bnet::
|
45
|
+
rescue Bnet::BadInputError, Bnet::RequestFailedError => e
|
46
46
|
raise Bnet::InvalidCommandException.new(e.message, name.to_sym)
|
47
47
|
end
|
48
48
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Bnet
|
2
|
+
|
3
|
+
CLIENT_MODEL = 'bn/authenticator'
|
4
|
+
RSA_MOD = 104890018807986556874007710914205443157030159668034197186125678960287470894290830530618284943118405110896322835449099433232093151168250152146023319326491587651685252774820340995950744075665455681760652136576493028733914892166700899109836291180881063097461175643998356321993663868233366705340758102567742483097
|
5
|
+
RSA_KEY = 257
|
6
|
+
AUTHENTICATOR_HOSTS = {
|
7
|
+
:CN => "mobile-service.battlenet.com.cn",
|
8
|
+
:EU => "m.eu.mobileservice.blizzard.com",
|
9
|
+
:US => "m.us.mobileservice.blizzard.com",
|
10
|
+
}
|
11
|
+
ENROLLMENT_REQUEST_PATH = '/enrollment/enroll.htm'
|
12
|
+
TIME_REQUEST_PATH = '/enrollment/time.htm'
|
13
|
+
RESTORE_INIT_REQUEST_PATH = '/enrollment/initiatePaperRestore.htm'
|
14
|
+
RESTORE_VALIDATE_REQUEST_PATH = '/enrollment/validatePaperRestore.htm'
|
15
|
+
|
16
|
+
RESTORECODE_MAP = (0..32).reduce({}) do |memo, c|
|
17
|
+
memo[c] = case
|
18
|
+
when c < 10 then c + 48
|
19
|
+
else
|
20
|
+
c += 55
|
21
|
+
c += 1 if c > 72 # S
|
22
|
+
c += 1 if c > 75 # O
|
23
|
+
c += 1 if c > 78 # L
|
24
|
+
c += 1 if c > 82 # I
|
25
|
+
c
|
26
|
+
end
|
27
|
+
memo
|
28
|
+
end
|
29
|
+
RESTORECODE_MAP_INVERSE = RESTORECODE_MAP.invert
|
30
|
+
|
31
|
+
end
|
data/lib/bnet/errors.rb
ADDED
@@ -17,15 +17,15 @@ class Bnet::AuthenticatorTest < Minitest::Test
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_argument_error
|
20
|
-
assert_raises ::Bnet::
|
20
|
+
assert_raises ::Bnet::BadInputError do
|
21
21
|
Bnet::Authenticator.new('ABC', '')
|
22
22
|
end
|
23
23
|
|
24
|
-
assert_raises ::Bnet::
|
24
|
+
assert_raises ::Bnet::BadInputError do
|
25
25
|
Bnet::Authenticator.request_authenticator('SG')
|
26
26
|
end
|
27
27
|
|
28
|
-
assert_raises ::Bnet::
|
28
|
+
assert_raises ::Bnet::BadInputError do
|
29
29
|
Bnet::Authenticator.restore_authenticator('DDDD', 'EEE')
|
30
30
|
end
|
31
31
|
end
|
@@ -37,7 +37,7 @@ class Bnet::AuthenticatorTest < Minitest::Test
|
|
37
37
|
refute_nil authenticator.serial
|
38
38
|
refute_nil authenticator.secret
|
39
39
|
refute_nil authenticator.restorecode
|
40
|
-
rescue Bnet::
|
40
|
+
rescue Bnet::RequestFailedError => e
|
41
41
|
puts e
|
42
42
|
end
|
43
43
|
end
|
@@ -46,7 +46,7 @@ class Bnet::AuthenticatorTest < Minitest::Test
|
|
46
46
|
begin
|
47
47
|
authenticator = Bnet::Authenticator.restore_authenticator(DEFAULT_SERIAL, DEFAULT_RSCODE)
|
48
48
|
is_default_authenticator authenticator
|
49
|
-
rescue Bnet::
|
49
|
+
rescue Bnet::RequestFailedError => e
|
50
50
|
puts e
|
51
51
|
end
|
52
52
|
end
|
@@ -54,7 +54,7 @@ class Bnet::AuthenticatorTest < Minitest::Test
|
|
54
54
|
def test_request_server_time
|
55
55
|
begin
|
56
56
|
Bnet::Authenticator.request_server_time :EU
|
57
|
-
rescue Bnet::
|
57
|
+
rescue Bnet::RequestFailedError => e
|
58
58
|
puts e
|
59
59
|
end
|
60
60
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bnet-authenticator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ZHANG Yi
|
@@ -82,15 +82,16 @@ files:
|
|
82
82
|
- bin/bna
|
83
83
|
- bnet-authenticator.gemspec
|
84
84
|
- lib/bnet/authenticator.rb
|
85
|
-
- lib/bnet/authenticator/constants.rb
|
86
|
-
- lib/bnet/authenticator/errors.rb
|
87
85
|
- lib/bnet/authenticator/version.rb
|
86
|
+
- lib/bnet/authenticator_helper.rb
|
88
87
|
- lib/bnet/command.rb
|
89
88
|
- lib/bnet/commands/help.rb
|
90
89
|
- lib/bnet/commands/info.rb
|
91
90
|
- lib/bnet/commands/new.rb
|
92
91
|
- lib/bnet/commands/restore.rb
|
93
92
|
- lib/bnet/commands/token.rb
|
93
|
+
- lib/bnet/constants.rb
|
94
|
+
- lib/bnet/errors.rb
|
94
95
|
- lib/bnet/support.rb
|
95
96
|
- test/test_battlenet_authenticator.rb
|
96
97
|
homepage: https://github.com/dorentus/bnet-authenticator
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Bnet
|
2
|
-
|
3
|
-
class Authenticator
|
4
|
-
|
5
|
-
CLIENT_MODEL = 'bn/authenticator'
|
6
|
-
RSA_MOD = 104890018807986556874007710914205443157030159668034197186125678960287470894290830530618284943118405110896322835449099433232093151168250152146023319326491587651685252774820340995950744075665455681760652136576493028733914892166700899109836291180881063097461175643998356321993663868233366705340758102567742483097
|
7
|
-
RSA_KEY = 257
|
8
|
-
AUTHENTICATOR_HOSTS = {
|
9
|
-
:CN => "mobile-service.battlenet.com.cn",
|
10
|
-
:EU => "m.eu.mobileservice.blizzard.com",
|
11
|
-
:US => "m.us.mobileservice.blizzard.com",
|
12
|
-
}
|
13
|
-
ENROLLMENT_REQUEST_PATH = '/enrollment/enroll.htm'
|
14
|
-
TIME_REQUEST_PATH = '/enrollment/time.htm'
|
15
|
-
RESTORE_INIT_REQUEST_PATH = '/enrollment/initiatePaperRestore.htm'
|
16
|
-
RESTORE_VALIDATE_REQUEST_PATH = '/enrollment/validatePaperRestore.htm'
|
17
|
-
|
18
|
-
RESTORECODE_MAP = (0..32).reduce({}) do |memo, c|
|
19
|
-
memo[c] = case
|
20
|
-
when c < 10 then c + 48
|
21
|
-
else
|
22
|
-
c += 55
|
23
|
-
c += 1 if c > 72 # S
|
24
|
-
c += 1 if c > 75 # O
|
25
|
-
c += 1 if c > 78 # L
|
26
|
-
c += 1 if c > 82 # I
|
27
|
-
c
|
28
|
-
end
|
29
|
-
memo
|
30
|
-
end
|
31
|
-
RESTORECODE_MAP_INVERSE = RESTORECODE_MAP.invert
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|