bnet-authenticator 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|