Skip to content

Commit d6edbdf

Browse files
authored
Reintroduce Timing-Safe Signature Verification in v2 Webhook Parser (#435)
Resolve #428 In v1, we had a constant-time signature comparison to mitigate timing attacks. - https://github.com/line/line-bot-sdk-ruby/blob/a6db291b252b13116b67f9b3621f73d3694b35bc/lib/line/bot/v1/client.rb#L1654-L1691 In v2(before release), this check was removed. This patch reintroduces timing-safe verification, ensuring that the request body and the `x-line-signature` header are validated without leaking timing information.
1 parent 8b970da commit d6edbdf

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

lib/line/bot/v2/webhook_parser.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,23 @@ def parse(body, signature)
4141

4242
def verify_signature(body:, signature:)
4343
hash = OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), @channel_secret, body)
44-
signature == Base64.strict_encode64(hash.to_s)
44+
expected = Base64.strict_encode64(hash)
45+
variable_secure_compare(signature, expected)
46+
end
47+
48+
# To avoid timing attacks
49+
def variable_secure_compare(a, b)
50+
secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
51+
end
52+
53+
def secure_compare(a, b)
54+
return false unless a.bytesize == b.bytesize
55+
56+
l = a.unpack("C#{a.bytesize}")
57+
58+
res = 0
59+
b.each_byte { |byte| res |= byte ^ l.shift }
60+
res == 0
4561
end
4662

4763
def create_instance(klass, attributes)

sig/line/bot/v2/webhook_parser.rbs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ module Line
88

99
private
1010

11+
def variable_secure_compare: (a: String, b: String) -> bool
12+
13+
def secure_compare: (a: String, b: String) -> bool
14+
1115
def verify_signature: (body: String, signature: String) -> bool
1216

1317
def create_instance: (untyped klass, Hash[Symbol, untyped] attributes) -> untyped

0 commit comments

Comments
 (0)