mask-privacy 4.2.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +25 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +25 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/core/fpe.ts +48 -23
- package/src/core/fpe_utils.ts +4 -4
- package/tests/bijective_fpe.test.ts +2 -2
- package/tests/compliance_pci.test.ts +53 -0
- package/tests/fpe.test.ts +2 -2
package/dist/index.mjs
CHANGED
|
@@ -689,7 +689,7 @@ function looksLikeToken(value) {
|
|
|
689
689
|
if (v7.includes("-") && v7.length >= 6) {
|
|
690
690
|
const parts = v7.split("-");
|
|
691
691
|
const tag = parts[parts.length - 1];
|
|
692
|
-
if (tag.length
|
|
692
|
+
if (tag.length >= 3 && tag.length <= 10 && /^\d+$/.test(tag)) {
|
|
693
693
|
return true;
|
|
694
694
|
}
|
|
695
695
|
}
|
|
@@ -709,14 +709,14 @@ function isUnambiguouslySafeToken(value) {
|
|
|
709
709
|
if (/^[A-Z]{2}00[A-F0-9]{4,16}$/.test(v7)) return true;
|
|
710
710
|
if (/^<(PER|LOC|ORG):[^>]+>$/.test(v7)) return true;
|
|
711
711
|
if (v7.startsWith("[TKN-") && v7.endsWith("]")) return true;
|
|
712
|
-
if (/^[A-Z][a-zA-Z, ]+-[0-9]{3,
|
|
712
|
+
if (/^[A-Z][a-zA-Z, ]+-[0-9]{3,10}$/.test(v7)) return true;
|
|
713
713
|
return false;
|
|
714
714
|
}
|
|
715
715
|
var TOKEN_PATTERN;
|
|
716
716
|
var init_fpe_utils = __esm({
|
|
717
717
|
"src/core/fpe_utils.ts"() {
|
|
718
718
|
TOKEN_PATTERN = new RegExp(
|
|
719
|
-
"tkn-[a-f0-9]{8,64}@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}|\\+[1-9]\\d{0,3}-555-\\d{7}|\\d{3}-\\d{2}-\\d{4}|\\d{4}-\\d{4}-\\d{4}-\\d{4}|\\b\\d{9}\\b|\\b000\\d{5}[A-Z]\\b|[A-Z]{2}00[A-F0-9]{4,16}|<(?:PER|LOC|ORG):[^>]+>|\\b[A-Z][a-zA-Z, ]+-[0-9]{3,
|
|
719
|
+
"tkn-[a-f0-9]{8,64}@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}|\\+[1-9]\\d{0,3}-555-\\d{7}|\\d{3}-\\d{2}-\\d{4}|\\d{4}-\\d{4}-\\d{4}-\\d{4}|\\b\\d{9}\\b|\\b000\\d{5}[A-Z]\\b|[A-Z]{2}00[A-F0-9]{4,16}|<(?:PER|LOC|ORG):[^>]+>|\\b[A-Z][a-zA-Z, ]+-[0-9]{3,10}\\b|\\[TKN-[^\\]]+\\]",
|
|
720
720
|
// Opaque
|
|
721
721
|
"g"
|
|
722
722
|
);
|
|
@@ -765,46 +765,46 @@ async function _getBijectiveTweak() {
|
|
|
765
765
|
async function _encryptBijectiveFF1(text) {
|
|
766
766
|
const canonical = text.toLowerCase().trim();
|
|
767
767
|
const hash = cryptoNode.createHash("sha256").update(canonical, "utf-8").digest();
|
|
768
|
-
const
|
|
769
|
-
const
|
|
768
|
+
const hash128 = hash.subarray(0, 16);
|
|
769
|
+
const inputInt = hash128.readBigUInt64BE(0) << 64n | hash128.readBigUInt64BE(8);
|
|
770
|
+
const inputStr = inputInt.toString().padStart(40, "0");
|
|
770
771
|
const aesKey = await _getAesKey();
|
|
771
772
|
const tweak = await _getBijectiveTweak();
|
|
772
773
|
const engine = new FF1(aesKey, tweak, 10);
|
|
773
774
|
const cipherStr = engine.encrypt(inputStr);
|
|
774
|
-
return BigInt(cipherStr)
|
|
775
|
+
return BigInt(cipherStr);
|
|
775
776
|
}
|
|
776
777
|
function _renderBijectivePerson(bits) {
|
|
777
778
|
const firstIdx = Number(bits & 0x7FFn);
|
|
778
779
|
const connIdx = Number(bits >> 11n & 0x3Fn);
|
|
779
780
|
const rootIdx = Number(bits >> 17n & 0xFFFn);
|
|
780
781
|
const suffixIdx = Number(bits >> 29n & 0x1FFn);
|
|
781
|
-
const tag =
|
|
782
|
-
const formatIdx = Number(bits >>
|
|
782
|
+
const tag = bits >> 38n & 0xFFFFFFFFFFn;
|
|
783
|
+
const formatIdx = Number(bits >> 78n & 0xFn);
|
|
783
784
|
const first = FIRST_NAMES[firstIdx % FIRST_NAMES.length];
|
|
784
785
|
const conn = CONNECTORS[connIdx % CONNECTORS.length];
|
|
785
786
|
const root = SURNAME_ROOTS[rootIdx % SURNAME_ROOTS.length];
|
|
786
787
|
const suffix = SURNAME_SUFFIXES[suffixIdx % SURNAME_SUFFIXES.length];
|
|
787
788
|
const surname = `${root}${suffix}`;
|
|
788
|
-
const numeric = tag %
|
|
789
|
-
const paddedNumeric = numeric.toString().padStart(
|
|
789
|
+
const numeric = Number(tag % 10000000000n);
|
|
790
|
+
const paddedNumeric = numeric.toString().padStart(10, "0");
|
|
790
791
|
if (formatIdx === 0) return `${first} ${conn} ${surname}-${paddedNumeric}`;
|
|
791
792
|
if (formatIdx === 1) return `${surname}, ${first}-${paddedNumeric}`;
|
|
792
793
|
if (formatIdx === 2) return `${first[0]}. ${surname}-${paddedNumeric}`;
|
|
793
|
-
if (formatIdx === 3) return `${first} ${surname}-${paddedNumeric}`;
|
|
794
794
|
return `${first} ${surname}-${paddedNumeric}`;
|
|
795
795
|
}
|
|
796
796
|
function _renderBijectiveLocation(bits) {
|
|
797
797
|
const s1 = Number(bits & 0x3FFn);
|
|
798
798
|
const s22 = Number(bits >> 10n & 0x3FFn);
|
|
799
799
|
const s32 = Number(bits >> 20n & 0x3FFn);
|
|
800
|
-
const tag =
|
|
800
|
+
const tag = bits >> 30n & 0xFFFFFFFFFFn;
|
|
801
801
|
const city = `${SYLLABLES[s1 % 1e3]}${SYLLABLES[s22 % 1e3].toLowerCase()}${SYLLABLES[s32 % 1e3].toLowerCase()}`;
|
|
802
|
-
return `${city}-${tag.toString().padStart(
|
|
802
|
+
return `${city}-${Number(tag % 10000000000n).toString().padStart(10, "0")}`;
|
|
803
803
|
}
|
|
804
|
-
function
|
|
805
|
-
const digits =
|
|
804
|
+
function _getLuhnSum(numStr) {
|
|
805
|
+
const digits = numStr.split("").map(Number);
|
|
806
806
|
let sum = 0;
|
|
807
|
-
let shouldDouble =
|
|
807
|
+
let shouldDouble = false;
|
|
808
808
|
for (let i6 = digits.length - 1; i6 >= 0; i6--) {
|
|
809
809
|
let digit = digits[i6];
|
|
810
810
|
if (shouldDouble) {
|
|
@@ -814,7 +814,7 @@ function _computeLuhnDigit(partialNum) {
|
|
|
814
814
|
sum += digit;
|
|
815
815
|
shouldDouble = !shouldDouble;
|
|
816
816
|
}
|
|
817
|
-
return
|
|
817
|
+
return sum;
|
|
818
818
|
}
|
|
819
819
|
function _computeEsIdCheck(num) {
|
|
820
820
|
return "TRWAGMYFPDXBNJZSQVHLCKE"[num % 23];
|
|
@@ -861,14 +861,15 @@ async function generateDPToken(rawText, entityType = "UNKNOWN") {
|
|
|
861
861
|
if (type === "CREDIT_CARD" || type === "CREDIT_CARD_NUMBER") {
|
|
862
862
|
const digits = _stripCcSeparators(text);
|
|
863
863
|
if (digits.length === 16) {
|
|
864
|
-
const
|
|
865
|
-
const
|
|
866
|
-
const
|
|
864
|
+
const prefix6 = digits.slice(0, 6);
|
|
865
|
+
const suffix4 = digits.slice(12, 16);
|
|
866
|
+
const middle5 = digits.slice(6, 11);
|
|
867
867
|
const engine = new FF1(await _getAesKey(), Buffer.from("CREDIT_CARD"), 10);
|
|
868
|
-
const
|
|
869
|
-
const
|
|
870
|
-
const
|
|
871
|
-
const
|
|
868
|
+
const encMiddle5 = engine.encrypt(middle5);
|
|
869
|
+
const draft = prefix6 + encMiddle5 + "0" + suffix4;
|
|
870
|
+
const sum = _getLuhnSum(draft);
|
|
871
|
+
const correction = (10 - sum % 10) % 10;
|
|
872
|
+
const full = prefix6 + encMiddle5 + correction.toString() + suffix4;
|
|
872
873
|
return `${full.slice(0, 4)}-${full.slice(4, 8)}-${full.slice(8, 12)}-${full.slice(12, 16)}`;
|
|
873
874
|
} else {
|
|
874
875
|
const fallbackDigits = digits.padEnd(16, "0").slice(0, 16);
|