diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-07-28 17:13:32 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-07-28 17:13:32 +0100 |
commit | 85933ea3363858cb510a2297edfd60c7e7adb98a (patch) | |
tree | 37cc2e7a9701fc028f11d0783e231636ce7f22c2 /rules/bitcoin.lua | |
parent | 8b5b86ec3841cdd82f29cbd6d0e23214a92b3271 (diff) | |
download | rspamd-85933ea3363858cb510a2297edfd60c7e7adb98a.tar.gz rspamd-85933ea3363858cb510a2297edfd60c7e7adb98a.zip |
[Project] Implement bitcoin cash validation in a proper way
Diffstat (limited to 'rules/bitcoin.lua')
-rw-r--r-- | rules/bitcoin.lua | 77 |
1 files changed, 32 insertions, 45 deletions
diff --git a/rules/bitcoin.lua b/rules/bitcoin.lua index 904ca660b..5ffd1a548 100644 --- a/rules/bitcoin.lua +++ b/rules/bitcoin.lua @@ -19,6 +19,7 @@ limitations under the License. local fun = require "fun" local bit = require "bit" local lua_util = require "lua_util" +local rspamd_util = require "rspamd_util" local N = "bitcoin" local off = 0 @@ -130,39 +131,7 @@ local function slice_table(tbl, first, last, step) return sliced end -local function btc_cash_polymod_step(c, byte) - --[[ - uint8_t c0 = c >> 35; - c = ((c & 0x07ffffffff) << 5) ^ d; - - if (c0 & 0x01) c ^= 0x98f2bc8e61; - if (c0 & 0x02) c ^= 0x79b76d99e2; - if (c0 & 0x04) c ^= 0xf33e5fb3c4; - if (c0 & 0x08) c ^= 0xae2eabe2a8; - if (c0 & 0x10) c ^= 0x1e4f43e470; ---]] - local c0 = bit.rshift(c, 35) - c = bit.bxor(bit.lshift(bit.band(c, 0x07ffffffff), 5), byte) - if bit.band(c0, 0x01) ~= 0 then - c = bit.bxor(c, 0x98f2bc8e61) - end - if bit.band(c0, 0x02) ~= 0 then - c = bit.bxor(c, 0x79b76d99e2) - end - if bit.band(c0, 0x04) ~= 0 then - c = bit.bxor(c, 0xf33e5fb3c4) - end - if bit.band(c0, 0x08) ~= 0 then - c = bit.bxor(c, 0xae2eabe2a8) - end - if bit.band(c0, 0x10) ~= 0 then - c = bit.bxor(c, 0x1e4f43e470) - end - - return c -end - -local function is_segwit_bech32_address(word) +local function is_segwit_bech32_address(task, word) local semicolon_pos = string.find(word, ':') local address_part = word if semicolon_pos then @@ -188,32 +157,31 @@ local function is_segwit_bech32_address(word) elseif semicolon_pos then -- Bitcoin cash address -- https://www.bitcoincash.org/spec/cashaddr.html - local l = require "rspamd_logger" local decoded = gen_bleach32_table(address_part) - l.errx('check %s, %s decoded', word, decoded) + lua_util.debugm(N, task, 'check %s, %s decoded', word, decoded) if decoded and #decoded > 8 then - -- TODO: Add checksum validation some day local c = 1 local prefix = word:sub(1, semicolon_pos - 1) + local polymod_tbl = {} fun.each(function(byte) - c = btc_cash_polymod_step(c, bit.band(string.byte(byte), 0x1f)) + local b = bit.band(string.byte(byte), 0x1f) + table.insert(polymod_tbl, b) end, fun.iter(prefix)) -- For semicolon - c = btc_cash_polymod_step(c, 0) + table.insert(polymod_tbl, 0) - fun.each(function(byte) c = btc_cash_polymod_step(c, byte) end, decoded) + fun.each(function(byte) c = table.insert(polymod_tbl, byte) end, decoded) + lua_util.debugm(N, task, 'final polymod table: %s', polymod_tbl) - if bit.bxor(c, 0x1) == 0 then - return true - end + return rspamd_util.btc_polymod(polymod_tbl) end end end -local normal_wallet_re = [[/\b[13LM][1-9A-Za-z]{25,34}\b/L{sa_body}]] -local btc_bleach_re = [[/\b(?:bc1|[13]|(?:[^:]+:))[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{14,}\b/L{sa_body}]] +local normal_wallet_re = [[/\b[13LM][1-9A-Za-z]{25,34}\b/AL{sa_body}]] +local btc_bleach_re = [[/\b(?:bc1|[13]|(?:\w+:))[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{14,}\b/AL{sa_body}]] config.regexp['BITCOIN_ADDR'] = { description = 'Message has a valid bitcoin wallet address', @@ -230,7 +198,7 @@ config.regexp['BITCOIN_ADDR'] = { if valid then -- To save option task:insert_result('BITCOIN_ADDR', 1.0, word) - lua_util.debugm(N, task, 'found valid tradtional bitcoin addr in the word: %s', + lua_util.debugm(N, task, 'found valid traditional bitcoin addr in the word: %s', word) return true else @@ -241,6 +209,25 @@ config.regexp['BITCOIN_ADDR'] = { end end, [btc_bleach_re] = function(task, txt, s, e) + if e - s <= 2 then + return false + end + + local word = tostring(lua_util.str_trim(txt:sub(s, e))) + local valid = is_segwit_bech32_address(task, word) + + if valid then + -- To save option + task:insert_result('BITCOIN_ADDR', 1.0, word) + lua_util.debugm(N, task, 'found valid bleach bitcoin addr in the word: %s', + word) + return true + else + lua_util.debugm(N, task, 'found invalid bitcoin addr in the word: %s', + word) + + return false + end end, }, callbackk = function(task) |