commit f99d7e2: [Rules] Refactor bleach32 addresses handling

Vsevolod Stakhov vsevolod at highsecure.ru
Fri Jun 19 20:28:06 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-06-19 17:19:59 +0100
URL: https://github.com/rspamd/rspamd/commit/f99d7e2a44e0ebe6372a7322329c2813119d8215

[Rules] Refactor bleach32 addresses handling

---
 rules/bitcoin.lua | 63 ++++++++++++++++++++++++++++---------------------------
 1 file changed, 32 insertions(+), 31 deletions(-)

diff --git a/rules/bitcoin.lua b/rules/bitcoin.lua
index 86380badf..d9c94fdf1 100644
--- a/rules/bitcoin.lua
+++ b/rules/bitcoin.lua
@@ -96,44 +96,45 @@ local function verify_beach32_cksum(hrp, elts)
   return polymod(hrpExpand(hrp), elts) == 1
 end
 
-local function is_segwit_bech32_address(word)
-  local has_upper, has_lower, has_invalid
-
-  if #word > 90 then return false end
+local function gen_bleach32_table(input)
+  local d = {}
+  local i = 1
+  local res = true
+  local charset = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
 
-  fun.each(function(ch)
-    if ch < 33 or ch > 126 then
-      has_invalid = true
-    elseif ch >= 97 and ch <= 122 then
-      has_lower = true
-    elseif ch >= 65 and ch <= 90 then
-      has_upper = true;
+  fun.each(function(byte)
+    if res then
+      local pos = charset:find(byte)
+      if not pos then
+        res = false
+      else
+        d[i] = pos - 1
+        i = i + 1
+      end
     end
-  end, fun.map(string.byte, fun.iter(word)))
+  end, fun.iter(input))
 
-  if has_invalid or (has_lower and has_upper) then
-    return false
-  end
+  return res and d or nil
+end
 
-  word = word:lower()
-  local last_one_pos = word:find('1[^1]*$')
-  if not last_one_pos or (last_one_pos < 1 or last_one_pos + 7 > #word) then
-    return false
-  end
-  local hrp = word:sub(1, last_one_pos - 1)
-  local d = {}
-  local charset = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
-  for i=last_one_pos + 1,#word do
-    local c = word:sub(i, i)
-    local pos = charset:find(c)
+local function is_segwit_bech32_address(word)
+  local prefix = word:sub(1, 3)
 
-    if not pos then
+  if prefix == 'bc1' or prefix.sub(1, 1) == '1' or prefix.sub(1, 1) == '3' then
+    -- Strip beach32 prefix in bitcoin
+    word = word:lower()
+    local last_one_pos = word:find('1[^1]*$')
+    if not last_one_pos or (last_one_pos < 1 or last_one_pos + 7 > #word) then
       return false
     end
-    d[#d + 1] = pos - 1
-  end
+    local hrp = word:sub(1, last_one_pos - 1)
+    local addr = word:sub(last_one_pos + 1, -1)
+    local decoded = gen_bleach32_table(addr)
 
-  return verify_beach32_cksum(hrp, d)
+    if decoded then
+      return verify_beach32_cksum(hrp, decoded)
+    end
+  end
 end
 
 
@@ -144,7 +145,7 @@ rspamd_config:register_symbol{
     local rspamd_re = require "rspamd_regexp"
 
     local btc_wallet_re = rspamd_re.create_cached('^[13LM][1-9A-Za-z]{25,34}$')
-    local segwit_wallet_re = rspamd_re.create_cached('^[b][c]1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{14,74}$', 'i')
+    local segwit_wallet_re = rspamd_re.create_cached('^(?:bc1|[13])?[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{14,}$', 'i')
     local words_matched = {}
     local segwit_words_matched = {}
     local valid_wallets = {}


More information about the Commits mailing list