data_masker 1.0.1
data_masker: ^1.0.1 copied to clipboard
Pure Dart data masking library for sensitive data anonymization. Supports phone, email, ID card, bank card and custom rules.
data_masker #
Pure Dart data masking library for sensitive data anonymization. Works on all Dart platforms with zero dependencies.
Quick Results #
See what data_masker can do at a glance:
| Data Type | Input | Output |
|---|---|---|
| Phone | 13812345678 |
138****5678 |
user@example.com |
use***@example.com |
|
| ID Card | 110101199001011234 |
110101********1234 |
| Bank Card | 6222021234567890123 |
6222***********0123 |
| IP Address | 192.168.1.100 |
192.168.***.100 |
| URL | https://example.com/api/users |
https://example.com******** |
| Passport | G12345678 |
G****** |
| License Plate | CA12345 |
CA1*** |
| JWT Token | eyJhbGciOiJIUzI1Ni...w5c |
eyJhbGci****************w5c |
| UUID | 550e8400-e29b-41d4-a716-...0000 |
550e8400-****-****-****-446655440000 |
| API Key | sk_test_abcdefghijklmnop... |
sk_************ |
| Chinese Name | Zhang San, Zhang Sanfeng |
Zhang ***, Zhang *** |
| English Name | John Doe |
John D*** |
| Date of Birth | 1990-01-01 |
1990-01-** |
Features #
- Cross-platform: Pure Dart implementation, works everywhere Dart runs
- 15+ Preset Rules: Phone, email, ID card, bank card, IP, URL, passport, license plate, JWT, UUID, API key, names, date of birth
- 4 Mask Strategies: Full mask, keep prefix, keep suffix, keep both ends
- Custom Rules: Field name matching, regex matching, custom logic
- Nested Support: Recursively masks nested Map and List structures
- Type Safe: Full null safety support
- Dart 2.19+: Compatible with a wide range of Dart versions
Getting Started #
Installation #
dependencies:
data_masker: ^1.0.0
dart pub get
Basic Usage #
import 'package:data_masker/data_masker.dart';
void main() {
final config = MaskConfig(
enabled: true,
rules: [
PresetMaskRules.phone(),
PresetMaskRules.email(),
FieldMaskRule(fieldNames: ['password', 'token']),
],
);
final masker = DataMasker(config);
// Mask string
final maskedString = masker.process('Phone: 13812345678, Email: user@example.com');
print(maskedString);
// Output: Phone: 138****5678, Email: use***@example.com
// Mask Map
final maskedMap = masker.process({
'username': 'test',
'password': 'secret123',
'phone': '13812345678',
});
print(maskedMap);
// Output: {username: test, password: *********, phone: 138****5678}
// Mask nested structure
final nestedData = {
'user': {
'name': 'Zhang San',
'auth': {'token': 'abc123xyz'}
},
'contacts': [{'phone': '13987654321'}],
};
final maskedNested = masker.process(nestedData);
print(maskedNested);
// Output: {user: {name: Zhang ***, auth: {token: *********}}, contacts: [{phone: 139****4321}]}
}
Run Example #
dart run example/data_masker_example.dart
Actual Output:
=== data_masker Complete Example ===
1. MaskStrategy (Masking Strategy)
full: **********
keepPrefix: 123*******
keepSuffix: ******7890
keepBoth: 123****890
2. PresetMaskRules (Preset Rules)
Phone: 138****5678
Email: use***@example.com
ID Card: 110101********1234
Bank Card: 6222***********0123
IP Address: 192.168.***.100
URL: https://example.com********
3. Supported Data Types
String: Phone: 138****5678, Email: use***@example.com
Map: {username: test, password: *********, phone: 138****5678}
List: [{name: Alice, email: ali***@example.com}, {name: Bob, email: bob***@example.com}]
4. Real-world Scenario
API Response Masking:
{code: 200, message: success, data: {user: {id: 123, name: Zhang ***, phone: 138****5678, email: zha***@company.com, idCard: 110101********1234, bankCard: 6222***********0123}, session: {token: ********************, expireTime: 2024-12-31 23:59:59}}}
API Documentation #
MaskStrategy #
Enumeration defining the masking strategy.
| Strategy | Description | Example |
|---|---|---|
full |
Mask entire value | 1234567890 → ********** |
keepPrefix |
Keep prefix, mask rest | 1234567890 → 123******* |
keepSuffix |
Keep suffix, mask rest | 1234567890 → ******7890 |
keepBoth |
Keep both ends, mask middle | 1234567890 → 123****890 |
MaskConfig #
const MaskConfig({
this.enabled = false, // Enable/disable masking
this.defaultStrategy = MaskStrategy.full,
this.rules = const [], // List of mask rules
this.maskChar = '*', // Mask character: '*' or '#' or any
this.maxMaskLength = 20, // Maximum mask characters
this.caseSensitive = false, // Case sensitive field matching
});
Example:
final config = MaskConfig(
enabled: true,
maskChar: '#',
maxMaskLength: 10,
rules: [PresetMaskRules.phone()],
);
final masker = DataMasker(config);
print(masker.process('13812345678'));
// Output: 138####5678
DataMasker #
const DataMasker([this.config = const MaskConfig()]);
Object? process(Object? data);
Supported Types:
| Type | Behavior |
|---|---|
String |
Apply regex rules to find and mask patterns |
Map |
Recursively process keys and values |
Iterable |
Recursively process each item |
| Other | Convert to string and apply rules |
Example:
final masker = DataMasker(MaskConfig(
enabled: true,
rules: [PresetMaskRules.email()],
));
// Process String
masker.process('Contact: alice@example.com');
// Output: Contact: ali***@example.com
// Process Map
masker.process({'email': 'bob@example.com'});
// Output: {email: bob***@example.com}
// Process List
masker.process([
{'name': 'Alice', 'email': 'alice@example.com'},
{'name': 'Bob', 'email': 'bob@example.com'},
]);
// Output: [{name: Alice, email: ali***@example.com}, {name: Bob, email: bob***@example.com}]
// Process nested structure
masker.process({
'user': {'name': 'John', 'auth': {'token': 'abc123'}}
});
// Output: {user: {name: John, auth: {token: *********}}}
FieldMaskRule #
Mask values based on field name matching.
const FieldMaskRule({
required this.fieldNames, // List of field names to match
super.strategy = MaskStrategy.full,
super.keepCount = 4,
super.customMask,
});
Example:
final rule = FieldMaskRule(
fieldNames: ['password', 'token', 'secret'],
strategy: MaskStrategy.keepPrefix,
keepCount: 2,
);
const config = MaskConfig(enabled: true);
// Check if field matches
rule.matches('password', 'secret123'); // true
rule.matches('username', 'test'); // false
// Apply mask
rule.apply('secret123', config); // 'se*********'
// Apply to JSON string
rule.applyToJsonString('{"password":"secret123"}', config);
// Output: {"password":"*********"}
RegexMaskRule #
Mask values based on regular expression matching.
const RegexMaskRule({
required this.pattern, // RegExp pattern to match
this.formatter, // Custom formatter function
super.strategy = MaskStrategy.full,
super.keepCount = 4,
super.customMask,
});
Example with Strategy:
final rule = RegexMaskRule(
pattern: RegExp(r'\d{6,8}'),
strategy: MaskStrategy.keepBoth,
keepCount: 3,
);
const config = MaskConfig(enabled: true);
rule.apply('ID: 12345678', config);
// Output: ID: 123**678
Example with Custom Formatter:
final rule = RegexMaskRule(
pattern: RegExp(r'(\d{3})\d{4}(\d{4})'),
formatter: (match, config) {
return '${match.group(1)}****${match.group(2)}';
},
);
rule.apply('13812345678', config);
// Output: 138****5678
CustomMaskRule #
Mask values with custom matching logic.
const CustomMaskRule({
required this.matcher, // Custom matcher function
this.formatter, // Custom formatter function
super.strategy = MaskStrategy.full,
super.keepCount = 4,
super.customMask,
});
Example:
// Custom matcher
final rule = CustomMaskRule(
matcher: (key, value) => key?.toString() == 'custom_field',
strategy: MaskStrategy.keepPrefix,
keepCount: 2,
);
rule.matches('custom_field', 'value'); // true
rule.matches('other_field', 'value'); // false
rule.apply('abcdef', config); // 'ab****'
// Custom formatter
final formatterRule = CustomMaskRule(
matcher: (key, value) => true,
formatter: (value) => '[MASKED]',
);
formatterRule.apply('sensitive data', config);
// Output: [MASKED]
MaskUtils #
static String applyMask(
String value,
MaskStrategy strategy,
int? keepCount,
String? customMask,
MaskConfig config,
);
Example:
MaskUtils.applyMask('1234567890', MaskStrategy.keepBoth, 3, null, config);
// Output: 123****890
MaskUtils.applyMask('secret', MaskStrategy.full, 4, '[HIDDEN]', config);
// Output: [HIDDEN]
PresetMaskRules #
Individual Rules
// Phone
PresetMaskRules.phone().apply('13812345678', config);
// Output: 138****5678
// Email
PresetMaskRules.email().apply('user@example.com', config);
// Output: use***@example.com
// ID Card
PresetMaskRules.idCard().apply('110101199001011234', config);
// Output: 110101********1234
// Bank Card
PresetMaskRules.bankCard().apply('6222021234567890123', config);
// Output: 6222***********0123
// IP Address
PresetMaskRules.ipAddress().apply('192.168.1.100', config);
// Output: 192.168.***.100
// URL
PresetMaskRules.url().apply('https://example.com/api/users', config);
// Output: https://example.com********
// Passport
PresetMaskRules.passport().apply('G12345678', config);
// Output: G******
// License Plate
PresetMaskRules.plateNumber().apply('CA12345', config);
// Output: CA1***
// JWT Token
PresetMaskRules.jwtToken().apply('eyJhbGciOiJIUzI1Ni...w5c', config);
// Output: eyJhbGci****************w5c
// UUID
PresetMaskRules.uuid().apply('550e8400-e29b-41d4-a716-446655440000', config);
// Output: 550e8400-****-****-****-446655440000
// API Key
PresetMaskRules.apiKey().apply('sk_test_abcdefghijklmnop', config);
// Output: sk_************
// Chinese Name (matches 2-4 Chinese characters)
// Pattern: [\u4e00-\u9fa5]{2,4}
// Keep first char, mask the rest
// English Name
PresetMaskRules.englishName().apply('John Doe', config);
// Output: John D***
// Date of Birth
PresetMaskRules.dateOfBirth().apply('1990-01-01', config);
// Output: 1990-01-**
Preset Combinations
Pre-configured rule combinations for common use cases:
// Financial data: bankCard + idCard + phone + commonFields
final financialConfig = MaskConfig(
enabled: true,
rules: PresetMaskRules.financial(),
);
// API logging: jwtToken + apiKey + email + ipAddress + url + commonFields
final apiLogConfig = MaskConfig(
enabled: true,
rules: PresetMaskRules.apiLog(),
);
// Personal info: phone + email + idCard + names + dateOfBirth + passport + commonFields
final personalConfig = MaskConfig(
enabled: true,
rules: PresetMaskRules.personalInfo(),
);
// Network logging: ipAddress + url + jwtToken + apiKey + email
final networkConfig = MaskConfig(
enabled: true,
rules: PresetMaskRules.networkLog(),
);
Advanced Usage #
Disable Masking #
final config = MaskConfig(
enabled: false, // All masking disabled
rules: [PresetMaskRules.phone()],
);
final masker = DataMasker(config);
masker.process('13812345678');
// Output: 13812345678 (unchanged)
Custom Mask Character #
final config = MaskConfig(
enabled: true,
maskChar: '#',
rules: [PresetMaskRules.phone()],
);
final masker = DataMasker(config);
masker.process('13812345678');
// Output: 138####5678
Multiple Rules #
final config = MaskConfig(
enabled: true,
rules: [
PresetMaskRules.phone(),
PresetMaskRules.email(),
FieldMaskRule(fieldNames: ['password', 'token']),
RegexMaskRule(pattern: RegExp(r'\d{8,}')),
],
);
final masker = DataMasker(config);
masker.process({
'phone': '13812345678',
'email': 'user@example.com',
'password': 'secret123',
});
// Output: {phone: 138****5678, email: use***@example.com, password: *********}
Platform Support #
- ✅ Flutter Android
- ✅ Flutter iOS
- ✅ Flutter Web
- ✅ Flutter Desktop (macOS, Linux, Windows)
- ✅ Dart CLI
- ✅ Dart Server
Dart Version #
- Minimum: Dart 2.19.0
- Recommended: Dart 3.0+
License #
MIT