Module: Legion::Extensions::Privatecore::Helpers::Patterns
- Defined in:
- lib/legion/extensions/privatecore/helpers/patterns.rb
Constant Summary collapse
- PATTERNS =
{ email: { regex: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/, category: :contact }, phone: { regex: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/, category: :contact }, ssn: { regex: /\b\d{3}-\d{2}-\d{4}\b/, category: :government_id }, ip: { regex: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/, category: :network }, credit_card: { regex: /\b(?:\d[ -]*?){13,19}\b/, category: :financial, checksum: :luhn }, dob: { regex: %r{(?:DOB|date of birth)\s*:\s*(\d{1,4}[-/]\d{1,2}[-/]\d{1,4})}i, category: :personal }, mrn: { regex: /(?:MRN|medical record)\s*:\s*(\d{5,15})/i, category: :medical }, passport: { regex: /\b[A-Z]\d{8}\b/, category: :government_id }, iban: { regex: /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/, category: :financial, checksum: :iban }, drivers_license: { regex: /\b[A-Z]\d{3}-?\d{4}-?\d{4}\b/, category: :government_id }, url: { regex: %r{https?://[^\s<>"{}|\\^`\[\]]+}, category: :network }, btc_address: { regex: /\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b/, category: :crypto, checksum: :base58check }, eth_address: { regex: /\b0x[0-9a-fA-F]{40}\b/, category: :crypto }, itin: { regex: /\b9\d{2}-[7-9]\d-\d{4}\b/, category: :government_id }, aadhaar: { regex: /\b[2-9]\d{3}\s?\d{4}\s?\d{4}\b/, category: :government_id, checksum: :verhoeff }, api_key: { regex: /\b(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{20,}\b/, category: :credential }, bearer_token: { regex: %r{Bearer\s+[A-Za-z0-9\-._~+/]+=*}, category: :credential }, aws_key: { regex: /\bAKIA[0-9A-Z]{16}\b/, category: :credential } }.freeze
- CHECKSUM_VALIDATORS =
{ luhn: ->(digits) { luhn_valid?(digits) }, iban: ->(text) { iban_valid?(text) }, verhoeff: ->(digits) { verhoeff_valid?(digits) }, base58check: ->(addr) { base58check_valid?(addr) } }.freeze
- VERHOEFF_D =
[ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 0, 6, 7, 8, 9, 5], [2, 3, 4, 0, 1, 7, 8, 9, 5, 6], [3, 4, 0, 1, 2, 8, 9, 5, 6, 7], [4, 0, 1, 2, 3, 9, 5, 6, 7, 8], [5, 9, 8, 7, 6, 0, 4, 3, 2, 1], [6, 5, 9, 8, 7, 1, 0, 4, 3, 2], [7, 6, 5, 9, 8, 2, 1, 0, 4, 3], [8, 7, 6, 5, 9, 3, 2, 1, 0, 4], [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] ].freeze
- VERHOEFF_P =
[ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8] ].freeze
- BASE58_ALPHABET =
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
Class Method Summary collapse
- .base58check_valid?(address) ⇒ Boolean
- .detect(text, enabled:, validation:) ⇒ Object
- .iban_valid?(iban) ⇒ Boolean
- .luhn_valid?(number) ⇒ Boolean
- .validate_checksum(type, match) ⇒ Object
- .verhoeff_valid?(number) ⇒ Boolean
Class Method Details
.base58check_valid?(address) ⇒ Boolean
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/legion/extensions/privatecore/helpers/patterns.rb', line 134 def base58check_valid?(address) return false unless address.match?(/\A[13][a-km-zA-HJ-NP-Z1-9]{25,34}\z/) # Decode Base58 to integer num = 0 address.each_char do |char| index = BASE58_ALPHABET.index(char) return false if index.nil? num = (num * 58) + index end # Convert to variable-length big-endian bytes, then restore # leading zero bytes represented by leading '1' characters. bytes = [] while num.positive? bytes.unshift(num & 0xff) num >>= 8 end leading_ones = address.each_char.take_while { |char| char == '1' }.size bytes = ([0] * leading_ones) + bytes # Base58Check P2PKH/P2SH addresses decode to: # 1 version byte + 20 payload bytes + 4 checksum bytes. return false unless bytes.size == 25 payload = bytes[0...-4] checksum = bytes[-4..] # Double SHA-256 of payload; compare first 4 bytes require 'digest' first_hash = Digest::SHA256.digest(payload.pack('C*')) second_hash = Digest::SHA256.digest(first_hash) second_hash.unpack('C*').first(4) == checksum end |
.detect(text, enabled:, validation:) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/legion/extensions/privatecore/helpers/patterns.rb', line 56 def detect(text, enabled:, validation:) return [] unless text.is_a?(String) detections = [] PATTERNS.each do |type, | next unless enabled.include?(type) text.scan([:regex]) do md = Regexp.last_match capture_index = md.captures.each_index.find { |index| !md[index + 1].nil? } match_index = capture_index ? capture_index + 1 : 0 matched_text = md[match_index] next if validation[type] == :checksum && !validate_checksum(type, matched_text) detections << { type: type, category: [:category], start: md.begin(match_index), end: md.end(match_index), match: matched_text } end end detections end |
.iban_valid?(iban) ⇒ Boolean
104 105 106 107 108 |
# File 'lib/legion/extensions/privatecore/helpers/patterns.rb', line 104 def iban_valid?(iban) rearranged = iban[4..] + iban[0..3] numeric = rearranged.chars.map { |c| c.match?(/\d/) ? c : (c.upcase.ord - 55).to_s }.join (numeric.to_i % 97) == 1 end |
.luhn_valid?(number) ⇒ Boolean
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/legion/extensions/privatecore/helpers/patterns.rb', line 93 def luhn_valid?(number) digits = number.chars.map(&:to_i) sum = 0 digits.reverse.each_with_index do |d, i| d *= 2 if i.odd? d -= 9 if d > 9 sum += d end (sum % 10).zero? end |
.validate_checksum(type, match) ⇒ Object
82 83 84 85 86 87 88 89 90 91 |
# File 'lib/legion/extensions/privatecore/helpers/patterns.rb', line 82 def validate_checksum(type, match) = PATTERNS[type] return true unless && [:checksum] validator = CHECKSUM_VALIDATORS[[:checksum]] return true unless validator cleaned = match.gsub(/[\s-]/, '') validator.call(cleaned) end |
.verhoeff_valid?(number) ⇒ Boolean
125 126 127 128 129 130 |
# File 'lib/legion/extensions/privatecore/helpers/patterns.rb', line 125 def verhoeff_valid?(number) digits = number.chars.map(&:to_i).reverse c = 0 digits.each_with_index { |d, i| c = VERHOEFF_D[c][VERHOEFF_P[i % 8][d]] } c.zero? end |