mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
@@ -85,8 +85,8 @@ android {
|
||||
applicationId "com.proofofpassportapp"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 14
|
||||
versionName "1.3"
|
||||
versionCode 15
|
||||
versionName "1.4"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags += "-fexceptions -frtti -std=c++11"
|
||||
|
||||
@@ -500,7 +500,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = OpenPassport/OpenPassportDebug.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 65;
|
||||
CURRENT_PROJECT_VERSION = 66;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 5B29R5LYHQ;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -615,7 +615,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
"$(PROJECT_DIR)/MoproKit/Libs",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.8;
|
||||
MARKETING_VERSION = 1.9.9;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -639,7 +639,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = OpenPassport/OpenPassport.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 65;
|
||||
CURRENT_PROJECT_VERSION = 66;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 5B29R5LYHQ;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@@ -753,7 +753,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
"$(PROJECT_DIR)/MoproKit/Libs",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.8;
|
||||
MARKETING_VERSION = 1.9.9;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
||||
@@ -9,7 +9,7 @@ const SplashScreen = () => {
|
||||
const { setSelectedTab } = useNavigationStore();
|
||||
useEffect(() => {
|
||||
if (userLoaded) {
|
||||
if (passportData) {
|
||||
if (passportData && passportData.dg2Hash && !passportData.mockUser) {
|
||||
setSelectedTab('app');
|
||||
} else {
|
||||
setSelectedTab('start');
|
||||
|
||||
@@ -230,13 +230,17 @@ const handleResponseAndroid = async (
|
||||
LDSVersion,
|
||||
unicodeVersion,
|
||||
encapContent,
|
||||
documentSigningCertificate
|
||||
documentSigningCertificate,
|
||||
dataGroupHashes
|
||||
} = response;
|
||||
|
||||
const dgHashesObj = JSON.parse(dataGroupHashes);
|
||||
const dg2Hash = dgHashesObj["2"]; // This will give you the DG2 hash
|
||||
const pem = "-----BEGIN CERTIFICATE-----" + documentSigningCertificate + "-----END CERTIFICATE-----"
|
||||
const passportData: PassportData = {
|
||||
mrz: mrz.replace(/\n/g, ''),
|
||||
dsc: pem,
|
||||
dg2Hash,
|
||||
eContent: JSON.parse(encapContent),
|
||||
signedAttr: JSON.parse(eContent),
|
||||
encryptedDigest: JSON.parse(encryptedDigest),
|
||||
|
||||
BIN
common/.yarn/install-state.gz
Normal file
BIN
common/.yarn/install-state.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
registry/.yarn/install-state.gz
Normal file
BIN
registry/.yarn/install-state.gz
Normal file
Binary file not shown.
1
registry/.yarnrc.yml
Normal file
1
registry/.yarnrc.yml
Normal file
@@ -0,0 +1 @@
|
||||
nodeLinker: node-modules
|
||||
@@ -1,278 +1,247 @@
|
||||
{
|
||||
"sha-1 ecdsa brainpoolP256r1": {
|
||||
"LT": 9,
|
||||
"LV": 9,
|
||||
"DE": 2,
|
||||
"BA": 2,
|
||||
"LTU": 1
|
||||
"ecdsa sha256 256 brainpoolP256r1": {
|
||||
"AE": 2,
|
||||
"CY": 8,
|
||||
"OM": 3
|
||||
},
|
||||
"sha-256 ecdsa secp256r1": {
|
||||
"BE": 7,
|
||||
"RW": 1,
|
||||
"rsa sha256 3072 65537": {
|
||||
"AR": 1,
|
||||
"CL": 3,
|
||||
"DK": 5,
|
||||
"LI": 1,
|
||||
"NL": 1,
|
||||
"PL": 5,
|
||||
"TL": 1,
|
||||
"UN": 2,
|
||||
"CO": 2,
|
||||
"MK": 2
|
||||
},
|
||||
"ecdsa sha384 384 brainpoolP384r1": {
|
||||
"AT": 3,
|
||||
"CH": 4,
|
||||
"CN": 2,
|
||||
"DE": 3,
|
||||
"LB": 1,
|
||||
"LV": 4,
|
||||
"PE": 1,
|
||||
"TH": 1,
|
||||
"UZ": 3,
|
||||
"BD": 1,
|
||||
"CR": 2,
|
||||
"PS": 1,
|
||||
"CY": 1
|
||||
},
|
||||
"rsa sha256 4096 38129": {
|
||||
"AT": 1
|
||||
},
|
||||
"rsa sha1 4096 65537": {
|
||||
"AU": 1,
|
||||
"BE": 2,
|
||||
"CN": 4,
|
||||
"HU": 4,
|
||||
"IT": 4,
|
||||
"MT": 6,
|
||||
"RO": 3,
|
||||
"VA": 2,
|
||||
"KZ": 2
|
||||
},
|
||||
"rsa sha256 4096 65537": {
|
||||
"AU": 4,
|
||||
"AZ": 3,
|
||||
"BB": 2,
|
||||
"BE": 4,
|
||||
"BG": 4,
|
||||
"BW": 3,
|
||||
"CN": 7,
|
||||
"EE": 2,
|
||||
"ES": 3,
|
||||
"FI": 3,
|
||||
"FR": 3,
|
||||
"GB": 3,
|
||||
"GE": 3,
|
||||
"GR": 8,
|
||||
"HU": 5,
|
||||
"IE": 3,
|
||||
"IL": 1,
|
||||
"KS": 3,
|
||||
"KW": 2,
|
||||
"MA": 3,
|
||||
"MC": 4,
|
||||
"ME": 2,
|
||||
"MT": 2,
|
||||
"NL": 5,
|
||||
"NO": 2,
|
||||
"NZ": 1,
|
||||
"PA": 2,
|
||||
"PT": 2,
|
||||
"QA": 2,
|
||||
"RO": 2,
|
||||
"SG": 2,
|
||||
"SI": 3,
|
||||
"SK": 5,
|
||||
"TH": 1,
|
||||
"TM": 4,
|
||||
"TR": 2,
|
||||
"TW": 5,
|
||||
"UA": 2,
|
||||
"US": 4,
|
||||
"UG": 2,
|
||||
"NP": 1,
|
||||
"UZ": 2,
|
||||
"ID": 3,
|
||||
"KE": 4,
|
||||
"CI": 3,
|
||||
"JM": 1,
|
||||
"AD": 4,
|
||||
"AL": 3,
|
||||
"SY": 1,
|
||||
"CM": 1
|
||||
},
|
||||
"ecdsa sha1 256 brainpoolP256r1": {
|
||||
"BA": 2,
|
||||
"LT": 4,
|
||||
"LV": 2
|
||||
},
|
||||
"ecdsa sha256 256 secp256r1": {
|
||||
"BE": 4,
|
||||
"RW": 2,
|
||||
"IN": 2,
|
||||
"SA": 1,
|
||||
"BJ": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 65537": {
|
||||
"PL": 11,
|
||||
"DK": 7,
|
||||
"CL": 5,
|
||||
"NL": 7,
|
||||
"AR": 2,
|
||||
"UN": 4,
|
||||
"TL": 1,
|
||||
"MK": 3,
|
||||
"LI": 1,
|
||||
"ZZ": 1,
|
||||
"NG": 1,
|
||||
"CO": 1,
|
||||
"VE": 1
|
||||
},
|
||||
"sha-256 rsa 4096 bit 65537": {
|
||||
"CN": 11,
|
||||
"FR": 5,
|
||||
"TR": 5,
|
||||
"FI": 7,
|
||||
"AL": 1,
|
||||
"GE": 4,
|
||||
"IE": 6,
|
||||
"MC": 4,
|
||||
"GR": 20,
|
||||
"AU": 9,
|
||||
"BE": 7,
|
||||
"MV": 1,
|
||||
"EE": 10,
|
||||
"NL": 8,
|
||||
"SG": 6,
|
||||
"RO": 5,
|
||||
"HU": 9,
|
||||
"ES": 7,
|
||||
"KS": 5,
|
||||
"KW": 2,
|
||||
"TM": 4,
|
||||
"UZ": 4,
|
||||
"SK": 5,
|
||||
"PA": 4,
|
||||
"TW": 6,
|
||||
"IL": 1,
|
||||
"MA": 5,
|
||||
"QA": 5,
|
||||
"BG": 5,
|
||||
"ME": 3,
|
||||
"PT": 4,
|
||||
"US": 9,
|
||||
"TH": 3,
|
||||
"SI": 6,
|
||||
"BB": 3,
|
||||
"NO": 5,
|
||||
"UA": 5,
|
||||
"MT": 5,
|
||||
"CI": 6,
|
||||
"NZ": 5,
|
||||
"BW": 4,
|
||||
"NP": 1,
|
||||
"AD": 3,
|
||||
"GB": 7,
|
||||
"ID": 3,
|
||||
"AZ": 3,
|
||||
"LT": 1,
|
||||
"GA": 1,
|
||||
"UG": 3
|
||||
},
|
||||
"sha-256 rsa-pss unknown": {
|
||||
"SE": 9,
|
||||
"LU": 14,
|
||||
"CZ": 9,
|
||||
"KN": 1,
|
||||
"KR": 5,
|
||||
"CN": 14,
|
||||
"HR": 7,
|
||||
"NO": 3,
|
||||
"PH": 6,
|
||||
"CA": 6,
|
||||
"SG": 3,
|
||||
"PY": 1,
|
||||
"BS": 1,
|
||||
"IL": 3,
|
||||
"MY": 7,
|
||||
"SI": 1,
|
||||
"JP": 11,
|
||||
"EC": 1,
|
||||
"TZ": 5,
|
||||
"VC": 4,
|
||||
"MT": 1,
|
||||
"BH": 1,
|
||||
"BZ": 1,
|
||||
"GH": 1,
|
||||
"AG": 2,
|
||||
"AM": 1,
|
||||
"MN": 1
|
||||
},
|
||||
"sha-1 rsa 4096 bit 65537": {
|
||||
"CN": 5,
|
||||
"HU": 14,
|
||||
"PT": 5,
|
||||
"BE": 4,
|
||||
"IT": 8,
|
||||
"RO": 6,
|
||||
"MT": 11,
|
||||
"VA": 3,
|
||||
"ES": 2,
|
||||
"FR": 1,
|
||||
"AU": 4,
|
||||
"MC": 4,
|
||||
"KZ": 3,
|
||||
"PH": 2,
|
||||
"LU": 4
|
||||
},
|
||||
"sha-512 ecdsa brainpoolP512r1": {
|
||||
"ecdsa sha512 512 brainpoolP512r1": {
|
||||
"BR": 1,
|
||||
"DE": 3,
|
||||
"CH": 1,
|
||||
"DE": 2,
|
||||
"FI": 1,
|
||||
"VN": 1,
|
||||
"CH": 1
|
||||
"VN": 1
|
||||
},
|
||||
"sha-384 rsa-pss unknown": {
|
||||
"EU": 3,
|
||||
"RS": 4,
|
||||
"MK": 1,
|
||||
"TJ": 1
|
||||
},
|
||||
"sha-256 ecdsa brainpoolP256r1": {
|
||||
"CY": 13,
|
||||
"AE": 8,
|
||||
"OM": 3,
|
||||
"DE": 1
|
||||
},
|
||||
"sha-384 ecdsa brainpoolP384r1": {
|
||||
"DE": 7,
|
||||
"LB": 3,
|
||||
"LV": 7,
|
||||
"CH": 9,
|
||||
"PE": 1,
|
||||
"CN": 3,
|
||||
"AT": 3,
|
||||
"CY": 1,
|
||||
"TH": 1,
|
||||
"UZ": 5,
|
||||
"CR": 1
|
||||
},
|
||||
"sha-384 ecdsa secp384r1": {
|
||||
"GB": 2,
|
||||
"JP": 1,
|
||||
"rsapss sha256 4096 65537": {
|
||||
"BS": 1,
|
||||
"CA": 3,
|
||||
"HR": 4,
|
||||
"IL": 1,
|
||||
"BY": 1
|
||||
"JP": 1,
|
||||
"KN": 1,
|
||||
"LU": 7,
|
||||
"NO": 2,
|
||||
"PH": 4,
|
||||
"PY": 1,
|
||||
"SE": 2,
|
||||
"SG": 2,
|
||||
"VC": 2,
|
||||
"AG": 2,
|
||||
"CN": 1,
|
||||
"TZ": 3,
|
||||
"BZ": 1,
|
||||
"BH": 1,
|
||||
"GH": 1,
|
||||
"MN": 1,
|
||||
"EC": 1,
|
||||
"SI": 1,
|
||||
"DM": 1,
|
||||
"AM": 1,
|
||||
"GM": 3
|
||||
},
|
||||
"sha-256 rsa unknown": {
|
||||
"GB": 1,
|
||||
"TR": 2,
|
||||
"HU": 3,
|
||||
"AT": 1,
|
||||
"NZ": 1
|
||||
"rsapss sha256 4096 3": {
|
||||
"CN": 8
|
||||
},
|
||||
"sha-256 ecdsa brainpoolP384r1": {
|
||||
"UY": 1,
|
||||
"ecdsa sha256 384 brainpoolP384r1": {
|
||||
"CY": 1,
|
||||
"UY": 1
|
||||
},
|
||||
"rsapss sha256 3072 65537": {
|
||||
"CZ": 3,
|
||||
"MY": 3
|
||||
},
|
||||
"ecdsa sha384 512 brainpoolP512r1": {
|
||||
"DE": 1
|
||||
},
|
||||
"sha-384 rsa 4096 bit 65537": {
|
||||
"LI": 1
|
||||
"ecdsa sha512 unknown unknown": {
|
||||
"DZ": 2,
|
||||
"TR": 1
|
||||
},
|
||||
"sha-512 ecdsa secp384r1": {
|
||||
"ecdsa sha512 384 secp384r1": {
|
||||
"DZ": 1
|
||||
},
|
||||
"sha-512 ecdsa secp384r1 (NIST P-384)": {
|
||||
"DZ": 3
|
||||
"rsapss sha512 4096 65537": {
|
||||
"EE": 3,
|
||||
"IT": 2,
|
||||
"ME": 1
|
||||
},
|
||||
"sha-256 rsa 6144 bit 65537": {
|
||||
"MD": 5
|
||||
"rsapss sha384 4096 65537": {
|
||||
"EU": 2,
|
||||
"MK": 1
|
||||
},
|
||||
"sha-256 rsa 4096 bit 38129": {
|
||||
"AT": 2
|
||||
},
|
||||
"sha-512 rsa 4096 bit 65537": {
|
||||
"LI": 3,
|
||||
"IS": 2,
|
||||
"CM": 1,
|
||||
"MX": 1,
|
||||
"PT": 1,
|
||||
"KP": 1
|
||||
},
|
||||
"sha-512 ecdsa secp521r1": {
|
||||
"TR": 4,
|
||||
"ZW": 1,
|
||||
"IQ": 1
|
||||
},
|
||||
"sha-256 ecdsa secp384r1": {
|
||||
"NZ": 5,
|
||||
"HU": 3,
|
||||
"GB": 1,
|
||||
"ecdsa sha256 384 secp384r1": {
|
||||
"GB": 3,
|
||||
"HU": 2,
|
||||
"NZ": 4,
|
||||
"AE": 1,
|
||||
"SC": 1
|
||||
},
|
||||
"sha-1 ecdsa secp256r1": {
|
||||
"RU": 5
|
||||
"rsa sha512 4096 65537": {
|
||||
"IS": 1,
|
||||
"LI": 2,
|
||||
"CM": 2,
|
||||
"MX": 1,
|
||||
"AU": 1,
|
||||
"XO": 2,
|
||||
"KP": 1,
|
||||
"PT": 1
|
||||
},
|
||||
"sha-384 ecdsa brainpoolP512r1": {
|
||||
"DE": 1,
|
||||
"CH": 1
|
||||
},
|
||||
"sha-256 rsa 4096 bit 58097": {
|
||||
"ME": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 43459": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-512 rsa-pss unknown": {
|
||||
"IT": 2,
|
||||
"EE": 3,
|
||||
"MK": 1
|
||||
},
|
||||
"sha-1 rsa 4096 bit 3": {
|
||||
"VA": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 65537": {
|
||||
"IS": 2,
|
||||
"IN": 1
|
||||
},
|
||||
"sha-512 rsa unknown": {
|
||||
"FI": 1
|
||||
},
|
||||
"sha-512 ecdsa brainpoolP256r1": {
|
||||
"BA": 1
|
||||
},
|
||||
"sha-1 rsa 6144 bit 65537": {
|
||||
"MD": 3
|
||||
},
|
||||
"sha-1 rsa 2048 bit 65537": {
|
||||
"": 1,
|
||||
"SM": 1,
|
||||
"GE": 1,
|
||||
"rsa sha256 2048 65537": {
|
||||
"IS": 1
|
||||
},
|
||||
"sha-512 ecdsa secp521r1 (NIST P-521)": {
|
||||
"TR": 1
|
||||
"rsa sha384 4096 65537": {
|
||||
"JP": 1,
|
||||
"LI": 1,
|
||||
"AD": 1
|
||||
},
|
||||
"sha-384 ecdsa Unknown": {
|
||||
"JP": 1
|
||||
"ecdsa sha384 384 secp384r1": {
|
||||
"JP": 2,
|
||||
"BY": 1,
|
||||
"IL": 1
|
||||
},
|
||||
"sha-256 rsa 4096 bit 107903": {
|
||||
"NG": 1
|
||||
"rsapss sha256 3072 3": {
|
||||
"KR": 3
|
||||
},
|
||||
"sha-256 rsa 4096 bit 56611": {
|
||||
"IR": 2
|
||||
"rsa sha256 6144 65537": {
|
||||
"MD": 4
|
||||
},
|
||||
"sha-1 rsa 4096 bit 50633": {
|
||||
"rsa sha1 6144 65537": {
|
||||
"MD": 1
|
||||
},
|
||||
"rsapss sha384 3072 65537": {
|
||||
"RS": 4,
|
||||
"TJ": 2
|
||||
},
|
||||
"ecdsa sha1 256 secp256r1": {
|
||||
"RU": 3
|
||||
},
|
||||
"ecdsa sha512 521 secp521r1": {
|
||||
"TR": 3,
|
||||
"IS": 1,
|
||||
"HU": 2,
|
||||
"ZW": 1,
|
||||
"IQ": 1
|
||||
},
|
||||
"rsa sha256 4096 109729": {
|
||||
"SN": 1
|
||||
},
|
||||
"rsa sha1 4096 3": {
|
||||
"VA": 1
|
||||
},
|
||||
"rsa sha1 2048 65537": {
|
||||
"SM": 1
|
||||
},
|
||||
"rsa sha256 4096 56611": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-1 ecdsa secp384r1": {
|
||||
"CH": 1
|
||||
"rsa sha256 4096 107903": {
|
||||
"NG": 1
|
||||
},
|
||||
"sha-1 rsa 3072 bit 3": {
|
||||
"TH": 3
|
||||
},
|
||||
"sha-256 rsa 4096 bit 127485": {
|
||||
"SN": 1
|
||||
},
|
||||
"sha-256 rsa 4096 bit 109729": {
|
||||
"SN": 1
|
||||
"rsa sha384 3072 65537": {
|
||||
"TJ": 1
|
||||
}
|
||||
}
|
||||
@@ -1,284 +1,168 @@
|
||||
{
|
||||
"sha-256 rsa 2048 bit 65537": {
|
||||
"NZ": 182,
|
||||
"CN": 6961,
|
||||
"US": 1458,
|
||||
"FR": 2016,
|
||||
"MD": 67,
|
||||
"AU": 727,
|
||||
"rsa sha256 2048 65537": {
|
||||
"CN": 6223,
|
||||
"US": 1111,
|
||||
"FR": 1855,
|
||||
"MD": 40,
|
||||
"AU": 705,
|
||||
"IE": 85,
|
||||
"TH": 78,
|
||||
"UN": 37,
|
||||
"CO": 2,
|
||||
"TM": 356,
|
||||
"FI": 36,
|
||||
"TH": 16,
|
||||
"FI": 14,
|
||||
"HU": 12,
|
||||
"IS": 36,
|
||||
"IS": 30,
|
||||
"NZ": 40,
|
||||
"UN": 27,
|
||||
"ES": 83,
|
||||
"ID": 14,
|
||||
"TM": 211,
|
||||
"ID": 10,
|
||||
"SK": 42,
|
||||
"MA": 3,
|
||||
"MA": 1,
|
||||
"RO": 8,
|
||||
"BJ": 2,
|
||||
"PA": 43,
|
||||
"NG": 1,
|
||||
"GB": 2454,
|
||||
"AR": 16,
|
||||
"QA": 3,
|
||||
"SG": 45,
|
||||
"GB": 689,
|
||||
"AR": 5,
|
||||
"NO": 1,
|
||||
"UZ": 10
|
||||
},
|
||||
"sha-256 rsa-pss unknown": {
|
||||
"CN": 143,
|
||||
"CZ": 152,
|
||||
"JP": 127,
|
||||
"KR": 194,
|
||||
"CA": 755,
|
||||
"SG": 24,
|
||||
"rsapss sha256 2048 65537": {
|
||||
"CZ": 111,
|
||||
"JP": 51,
|
||||
"CA": 522,
|
||||
"LU": 109,
|
||||
"SE": 296,
|
||||
"SG": 20,
|
||||
"SE": 63,
|
||||
"CN": 57,
|
||||
"TZ": 89,
|
||||
"MY": 189,
|
||||
"BZ": 14,
|
||||
"MN": 5,
|
||||
"BH": 5
|
||||
},
|
||||
"sha-256 rsa 4096 bit 65537": {
|
||||
"BG": 90,
|
||||
"UA": 44,
|
||||
"rsapss sha256 2048 3": {
|
||||
"CN": 54,
|
||||
"KR": 92,
|
||||
"JP": 1
|
||||
},
|
||||
"rsa sha256 4096 65537": {
|
||||
"BG": 64,
|
||||
"UA": 43,
|
||||
"IS": 38
|
||||
},
|
||||
"sha-256 ecdsa secp256r1": {
|
||||
"ecdsa sha256 256 secp256r1": {
|
||||
"GB": 1572,
|
||||
"NZ": 52,
|
||||
"HU": 19,
|
||||
"RW": 5,
|
||||
"BJ": 1
|
||||
},
|
||||
"sha-384 ecdsa brainpoolP256r1": {
|
||||
"ecdsa sha384 256 brainpoolP256r1": {
|
||||
"AT": 48,
|
||||
"CH": 195,
|
||||
"DE": 31
|
||||
"CH": 162,
|
||||
"DE": 18
|
||||
},
|
||||
"sha-256 rsa 2048 bit 3": {
|
||||
"IE": 469
|
||||
"rsa sha256 2048 3": {
|
||||
"IE": 415
|
||||
},
|
||||
"sha-1 rsa 2048 bit 65537": {
|
||||
"CN": 90,
|
||||
"ES": 84,
|
||||
"IT": 21,
|
||||
"FR": 32,
|
||||
"AU": 68,
|
||||
"HU": 68,
|
||||
"LU": 2
|
||||
},
|
||||
"sha-256 ecdsa brainpoolP256r1": {
|
||||
"AE": 50,
|
||||
"ecdsa sha256 256 brainpoolP256r1": {
|
||||
"UA": 2,
|
||||
"CN": 23,
|
||||
"AE": 13,
|
||||
"TH": 15
|
||||
},
|
||||
"sha-256 rsa unknown": {
|
||||
"UA": 2
|
||||
"rsa sha1 2048 65537": {
|
||||
"ES": 21,
|
||||
"IT": 8,
|
||||
"HU": 18
|
||||
},
|
||||
"sha-256 rsa 3072 bit 64999": {
|
||||
"rsa sha256 3072 64999": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 62391": {
|
||||
"rsa sha256 3072 62391": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-384 ecdsa secp384r1": {
|
||||
"ecdsa sha384 384 secp384r1": {
|
||||
"JP": 56
|
||||
},
|
||||
"sha-256 rsa 3072 bit 49861": {
|
||||
"rsa sha256 3072 49861": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 37399": {
|
||||
"rsa sha256 3072 37399": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 65223": {
|
||||
"rsa sha256 3072 65223": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 44459": {
|
||||
"rsa sha256 3072 44459": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 54007": {
|
||||
"rsa sha256 3072 54007": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-512 rsa-pss unknown": {
|
||||
"rsapss sha512 2048 65537": {
|
||||
"IT": 36
|
||||
},
|
||||
"sha-384 rsa-pss unknown": {
|
||||
"rsapss sha384 2048 65537": {
|
||||
"EU": 11
|
||||
},
|
||||
"sha-256 rsa 3072 bit 49729": {
|
||||
"rsa sha256 3072 49729": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 52355": {
|
||||
"rsa sha256 3072 52355": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 42239": {
|
||||
"rsapss sha256 3072 65537": {
|
||||
"SE": 91,
|
||||
"CA": 133,
|
||||
"BZ": 14
|
||||
},
|
||||
"rsa sha256 3072 42239": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-512 rsa 2048 bit 65537": {
|
||||
"rsa sha512 2048 65537": {
|
||||
"MX": 12
|
||||
},
|
||||
"sha-256 rsa 3072 bit 55443": {
|
||||
"rsa sha256 3072 55443": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 34389": {
|
||||
"rsa sha256 3072 34389": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 58333": {
|
||||
"rsa sha256 3072 58333": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 65537": {
|
||||
"rsa sha256 3072 65537": {
|
||||
"NP": 104,
|
||||
"FI": 8
|
||||
},
|
||||
"sha-256 ecdsa secp384r1": {
|
||||
"ecdsa sha256 384 secp384r1": {
|
||||
"AE": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 45347": {
|
||||
"rsa sha256 3072 45347": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-256 ecdsa Unknown": {
|
||||
"BJ": 2
|
||||
},
|
||||
"sha-256 rsa 3072 bit 63289": {
|
||||
"rsa sha256 3072 63289": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-512 ecdsa brainpoolP512r1": {
|
||||
"ecdsa sha512 512 brainpoolP512r1": {
|
||||
"FI": 24,
|
||||
"BR": 2
|
||||
},
|
||||
"sha-256 rsa 3072 bit 60353": {
|
||||
"rsa sha256 3072 60353": {
|
||||
"IR": 1
|
||||
},
|
||||
"sha-512 ecdsa secp384r1": {
|
||||
"ecdsa sha512 384 secp384r1": {
|
||||
"IQ": 5
|
||||
},
|
||||
"sha-384 ecdsa brainpoolP384r1": {
|
||||
"ecdsa sha384 384 brainpoolP384r1": {
|
||||
"VN": 1
|
||||
},
|
||||
"sha-512 ecdsa brainpoolP256r1": {
|
||||
"ecdsa sha512 256 brainpoolP256r1": {
|
||||
"CH": 5
|
||||
},
|
||||
"sha-512 rsa 4096 bit 65537": {
|
||||
"rsa sha512 4096 65537": {
|
||||
"CM": 1
|
||||
},
|
||||
"sha-1 ecdsa Unknown curve": {
|
||||
"DE": 19
|
||||
},
|
||||
"sha-256 ecdsa Unknown curve": {
|
||||
"DE": 12,
|
||||
"AE": 42
|
||||
},
|
||||
"sha-256 rsa 1024 bit 65537": {
|
||||
"ZZ": 43
|
||||
},
|
||||
"sha-256 rsa 3072 bit 61181": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 48081": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 45279": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 51925": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 37121": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 35033": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 33579": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 35221": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 44681": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 44591": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 36515": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 62785": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 64113": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 36291": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 64721": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 65123": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 63701": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 53873": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 47415": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 42743": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 62765": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 53037": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 34779": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 59793": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 58127": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 33769": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 41817": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 33225": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 49371": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 65427": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 59575": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 53741": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 38105": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 3072 bit 61957": {
|
||||
"AT": 1
|
||||
},
|
||||
"sha-256 rsa 2048 bit 61735": {
|
||||
"rsa sha256 3072 44681": {
|
||||
"AT": 1
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,13 @@
|
||||
"prisma": "^5.18.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"@prisma/client": "^5.19.0",
|
||||
"@openpassport/zk-kit-imt": "^0.0.5",
|
||||
"@openpassport/zk-kit-lean-imt": "^0.0.6",
|
||||
"@openpassport/zk-kit-smt": "^0.0.1",
|
||||
"@peculiar/asn1-schema": "^2.3.13",
|
||||
"@peculiar/asn1-x509": "^2.3.13",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"@prisma/client": "^5.19.0",
|
||||
"asn1": "^0.2.6",
|
||||
"asn1.js": "^5.4.1",
|
||||
"asn1js": "^3.0.5",
|
||||
@@ -18,14 +20,17 @@
|
||||
"node-forge": "^1.3.1",
|
||||
"node-rsa": "^1.1.1",
|
||||
"pkijs": "^3.2.4",
|
||||
"poseidon-lite": "^0.2.0"
|
||||
"poseidon-lite": "^0.2.0",
|
||||
"x509-ts": "^0.13.0"
|
||||
},
|
||||
"scripts": {
|
||||
"install-registry": "cd ../common && yarn && cd ../registry && yarn",
|
||||
"db-init": "npx prisma generate",
|
||||
"db-push": "ts-node src/pushToDb.ts",
|
||||
"db-clear": "ts-node src/deleteDb.ts",
|
||||
"extract-masterlist": "ts-node src/extractMasterList.ts",
|
||||
"parse-data": "ts-node src/parseData.ts"
|
||||
"parse-data": "ts-node src/parseData.ts",
|
||||
"mapJson": "ts-node src/buildMapJson.ts"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "dsc_masterlist" (
|
||||
"id" TEXT NOT NULL,
|
||||
"issuer" TEXT,
|
||||
"hashAlgorithm" TEXT,
|
||||
"signatureAlgorithm" TEXT,
|
||||
"validity" JSONB,
|
||||
"subjectKeyIdentifier" TEXT,
|
||||
"publicKeyDetails" JSONB,
|
||||
"rawPem" TEXT,
|
||||
"rawTxt" TEXT,
|
||||
"pk_modulus" TEXT,
|
||||
"pk_exponent" TEXT,
|
||||
"pk_bits" TEXT,
|
||||
"pk_curve" TEXT,
|
||||
"pk_hashAlgorithm" TEXT,
|
||||
"pk_mgf" TEXT,
|
||||
"pk_saltLength" TEXT,
|
||||
|
||||
CONSTRAINT "dsc_masterlist_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "csca_masterlist" (
|
||||
"id" TEXT NOT NULL,
|
||||
"issuer" TEXT,
|
||||
"hashAlgorithm" TEXT,
|
||||
"signatureAlgorithm" TEXT,
|
||||
"validity" JSONB,
|
||||
"subjectKeyIdentifier" TEXT,
|
||||
"publicKeyDetails" JSONB,
|
||||
"rawPem" TEXT,
|
||||
"rawTxt" TEXT,
|
||||
"pk_modulus" TEXT,
|
||||
"pk_exponent" TEXT,
|
||||
"pk_bits" TEXT,
|
||||
"pk_curve" TEXT,
|
||||
"pk_hashAlgorithm" TEXT,
|
||||
"pk_mgf" TEXT,
|
||||
"pk_saltLength" TEXT,
|
||||
|
||||
CONSTRAINT "csca_masterlist_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "dsc_masterlist_pk_modulus_idx" ON "dsc_masterlist"("pk_modulus");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "dsc_masterlist_pk_bits_idx" ON "dsc_masterlist"("pk_bits");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "dsc_masterlist_pk_curve_idx" ON "dsc_masterlist"("pk_curve");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "dsc_masterlist_hashAlgorithm_idx" ON "dsc_masterlist"("hashAlgorithm");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "dsc_masterlist_signatureAlgorithm_idx" ON "dsc_masterlist"("signatureAlgorithm");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "dsc_masterlist_subjectKeyIdentifier_idx" ON "dsc_masterlist"("subjectKeyIdentifier");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "csca_masterlist_pk_modulus_idx" ON "csca_masterlist"("pk_modulus");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "csca_masterlist_pk_bits_idx" ON "csca_masterlist"("pk_bits");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "csca_masterlist_pk_curve_idx" ON "csca_masterlist"("pk_curve");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "csca_masterlist_hashAlgorithm_idx" ON "csca_masterlist"("hashAlgorithm");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "csca_masterlist_signatureAlgorithm_idx" ON "csca_masterlist"("signatureAlgorithm");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "csca_masterlist_subjectKeyIdentifier_idx" ON "csca_masterlist"("subjectKeyIdentifier");
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[id]` on the table `csca_masterlist` will be added. If there are existing duplicate values, this will fail.
|
||||
- A unique constraint covering the columns `[id]` on the table `dsc_masterlist` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "csca_masterlist_id_key" ON "csca_masterlist"("id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "dsc_masterlist_id_key" ON "dsc_masterlist"("id");
|
||||
3
registry/prisma/migrations/migration_lock.toml
Normal file
3
registry/prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
||||
@@ -14,7 +14,7 @@ datasource db {
|
||||
directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection
|
||||
}
|
||||
model dsc_masterlist {
|
||||
id String @id
|
||||
id String @id @unique
|
||||
issuer String?
|
||||
hashAlgorithm String?
|
||||
signatureAlgorithm String?
|
||||
@@ -23,9 +23,24 @@ model dsc_masterlist {
|
||||
publicKeyDetails Json?
|
||||
rawPem String? @db.Text
|
||||
rawTxt String? @db.Text
|
||||
|
||||
pk_modulus String?
|
||||
pk_exponent String?
|
||||
pk_bits String?
|
||||
pk_curve String?
|
||||
pk_hashAlgorithm String?
|
||||
pk_mgf String?
|
||||
pk_saltLength String?
|
||||
|
||||
@@index([pk_modulus])
|
||||
@@index([pk_bits])
|
||||
@@index([pk_curve])
|
||||
@@index([hashAlgorithm])
|
||||
@@index([signatureAlgorithm])
|
||||
@@index([subjectKeyIdentifier])
|
||||
}
|
||||
model csca_masterlist {
|
||||
id String @id
|
||||
id String @id @unique
|
||||
issuer String?
|
||||
hashAlgorithm String?
|
||||
signatureAlgorithm String?
|
||||
@@ -34,4 +49,19 @@ model csca_masterlist {
|
||||
publicKeyDetails Json?
|
||||
rawPem String? @db.Text
|
||||
rawTxt String? @db.Text
|
||||
|
||||
pk_modulus String?
|
||||
pk_exponent String?
|
||||
pk_bits String?
|
||||
pk_curve String?
|
||||
pk_hashAlgorithm String?
|
||||
pk_mgf String?
|
||||
pk_saltLength String?
|
||||
|
||||
@@index([pk_modulus])
|
||||
@@index([pk_bits])
|
||||
@@index([pk_curve])
|
||||
@@index([hashAlgorithm])
|
||||
@@index([signatureAlgorithm])
|
||||
@@index([subjectKeyIdentifier])
|
||||
}
|
||||
75
registry/src/buildMapJson.ts
Normal file
75
registry/src/buildMapJson.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { argv } from 'process';
|
||||
import { getPrismaClientFromEnv, prepareDataForInsertion } from './utils/prisma';
|
||||
import { parseCertificate } from './utils/certificateParsing/parseCertificate';
|
||||
import { CertificateData } from './utils/certificateParsing/dataStructure';
|
||||
|
||||
let pemDirectory: string;
|
||||
let tableName: 'csca_masterlist' | 'dsc_masterlist';
|
||||
|
||||
const certType = argv[2];
|
||||
|
||||
if (certType === 'csca') {
|
||||
pemDirectory = path.join(__dirname, '..', 'outputs', 'csca', 'pem_masterlist');
|
||||
tableName = 'csca_masterlist';
|
||||
} else if (certType === 'dsc') {
|
||||
pemDirectory = path.join(__dirname, '..', 'outputs', 'dsc', 'pem_masterlist');
|
||||
tableName = 'dsc_masterlist';
|
||||
} else {
|
||||
console.error('Invalid certificate type. Use "csca" or "dsc".');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function main() {
|
||||
let mapJson: { [key: string]: { [key: string]: number } } = {};
|
||||
let certificates: { [key: string]: CertificateData } = {};
|
||||
try {
|
||||
const files = fs.readdirSync(pemDirectory);
|
||||
for (const file of files) {
|
||||
const pemContent = fs.readFileSync(path.join(pemDirectory, file), 'utf8');
|
||||
try {
|
||||
const certificate = parseCertificate(pemContent, file);
|
||||
if (certificate) {
|
||||
const notAfterDate = new Date(certificate.validity.notAfter);
|
||||
if (notAfterDate > new Date()) {
|
||||
certificates[certificate.id] = certificate;
|
||||
} else {
|
||||
console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is expired.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is invalid.`);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('error:', error);
|
||||
}
|
||||
for (const cert of Object.values(certificates)) {
|
||||
const issuer = cert.issuer;
|
||||
const signatureAlgorithm = cert.signatureAlgorithm;
|
||||
const hashAlgorithm = cert.hashAlgorithm;
|
||||
const bits = cert.publicKeyDetails?.bits || 'unknown';
|
||||
|
||||
const pubKeyType = cert.publicKeyDetails
|
||||
? ('exponent' in cert.publicKeyDetails ? cert.publicKeyDetails.exponent : cert.publicKeyDetails.curve)
|
||||
: 'unknown';
|
||||
|
||||
const certDescription = `${signatureAlgorithm} ${hashAlgorithm} ${bits} ${pubKeyType}`;
|
||||
|
||||
if (!mapJson[certDescription]) {
|
||||
mapJson[certDescription] = {};
|
||||
}
|
||||
if (!mapJson[certDescription][issuer]) {
|
||||
mapJson[certDescription][issuer] = 0;
|
||||
}
|
||||
|
||||
mapJson[certDescription][issuer]++;
|
||||
}
|
||||
fs.writeFileSync(path.join(__dirname, '..', 'outputs', certType, 'map_json.json'), JSON.stringify(mapJson, null, 2));
|
||||
}
|
||||
main();
|
||||
17
registry/src/deleteDb.ts
Normal file
17
registry/src/deleteDb.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// Create a script like clearDscTable.ts
|
||||
import { getPrismaClientFromEnv } from './utils/prisma';
|
||||
|
||||
async function clearDscTable() {
|
||||
const prisma = getPrismaClientFromEnv();
|
||||
try {
|
||||
await prisma.dsc_masterlist.deleteMany({});
|
||||
await prisma.csca_masterlist.deleteMany({});
|
||||
console.log('Successfully cleared dsc_masterlist and csca_masterlist tables');
|
||||
} catch (error) {
|
||||
console.error('Error clearing table:', error);
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
clearDscTable();
|
||||
@@ -1,48 +1,42 @@
|
||||
import { processCertificate } from "./utils/processCertificate";
|
||||
import { parseCertificate } from "./utils/certificateParsing/parseCertificate";
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { getListOfExponents, getMapJson } from "./utils/parseData";
|
||||
const csca_pem_directory_path = path.join(__dirname, '..', 'outputs', 'csca', 'pem_masterlist');
|
||||
const csca_pem_directory_path = path.join(__dirname, '..', 'outputs', 'csca', 'pem_masterlist copy');
|
||||
const dsc_pem_directory_path = path.join(__dirname, '..', 'outputs', 'dsc', 'pem_masterlist');
|
||||
import { CertificateData } from './utils/dataStructure';
|
||||
import { CertificateData } from './utils/certificateParsing/dataStructure';
|
||||
|
||||
function main(arg: string) {
|
||||
|
||||
// CSCA certificates
|
||||
if (arg === 'csca') {
|
||||
let csca_certificates: { [key: string]: CertificateData } = {};
|
||||
const seenSKIs = new Set<string>();
|
||||
const duplicates: string[] = [];
|
||||
|
||||
// Parse data
|
||||
const files = fs.readdirSync(csca_pem_directory_path);
|
||||
for (const file of files) {
|
||||
const pemContent = fs.readFileSync(path.join(csca_pem_directory_path, file), 'utf8');
|
||||
try {
|
||||
const certificate = processCertificate(pemContent, file);
|
||||
if (certificate) {
|
||||
const notAfterDate = new Date(certificate.validity.notAfter);
|
||||
if (notAfterDate > new Date()) {
|
||||
csca_certificates[file] = certificate;
|
||||
|
||||
} else {
|
||||
console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is expired.`);
|
||||
}
|
||||
}
|
||||
const certificate = parseCertificate(pemContent, file);
|
||||
}
|
||||
catch (error) {
|
||||
console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is invalid.`);
|
||||
console.log(error);
|
||||
// console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is invalid.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Get list of exponents
|
||||
const exponents = getListOfExponents(csca_certificates);
|
||||
console.log(exponents);
|
||||
// Log summary of duplicates
|
||||
if (duplicates.length > 0) {
|
||||
console.log('\x1b[33m%s\x1b[0m', `\nFound ${duplicates.length} duplicate certificates (by SKI):`);
|
||||
duplicates.forEach(file => console.log('\x1b[33m%s\x1b[0m', `- ${file}`));
|
||||
}
|
||||
|
||||
// Get map json
|
||||
// const mapJson = getMapJson(csca_certificates);
|
||||
// console.log(mapJson);
|
||||
|
||||
// Get map json
|
||||
// const skiPemJson = getSkiPemJson(csca_certificates);
|
||||
console.log('\nProcessed certificates:', Object.keys(csca_certificates).length);
|
||||
console.log('Unique SKIs:', seenSKIs.size);
|
||||
|
||||
// fs.writeFileSync(path.join(__dirname, '..', 'outputs', 'skiPemMasterList.json'), JSON.stringify(skiPemJson, null, 2));
|
||||
|
||||
}
|
||||
|
||||
@@ -53,25 +47,25 @@ function main(arg: string) {
|
||||
for (const file of files) {
|
||||
const pemContent = fs.readFileSync(path.join(dsc_pem_directory_path, file), 'utf8');
|
||||
try {
|
||||
const certificate = processCertificate(pemContent, file);
|
||||
// console.log('Parsing certificate:', file);
|
||||
const certificate = parseCertificate(pemContent, file);
|
||||
if (certificate) {
|
||||
const notAfterDate = new Date(certificate.validity.notAfter);
|
||||
if (notAfterDate > new Date()) {
|
||||
dsc_certificates[file] = certificate;
|
||||
|
||||
dsc_certificates[certificate.id] = certificate;
|
||||
} else {
|
||||
console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is expired.`);
|
||||
// console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is expired.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is invalid.`);
|
||||
// console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is invalid.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const exponents = getListOfExponents(dsc_certificates);
|
||||
console.log(exponents);
|
||||
// const exponents = getListOfExponents(dsc_certificates);
|
||||
// console.log(exponents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { processCertificate } from './utils/utils';
|
||||
import { argv } from 'process';
|
||||
import { getPrismaClientFromEnv, insertDB } from './utils/prisma';
|
||||
import { getPrismaClientFromEnv, prepareDataForInsertion } from './utils/prisma';
|
||||
import { parseCertificate } from './utils/certificateParsing/parseCertificate';
|
||||
|
||||
// Modify the pemDirectory and tableName declarations
|
||||
let pemDirectory: string;
|
||||
let tableName: 'csca_masterlist' | 'dsc_masterlist';
|
||||
|
||||
// Parse command-line argument
|
||||
const certType = argv[2];
|
||||
|
||||
if (certType === 'csca') {
|
||||
@@ -22,36 +20,85 @@ if (certType === 'csca') {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function processBatch(files: string[], prisma: any, startIdx: number, batchSize: number) {
|
||||
const endIdx = Math.min(startIdx + batchSize, files.length);
|
||||
const batchData = [];
|
||||
|
||||
for (let i = startIdx; i < endIdx; i++) {
|
||||
const file = files[i];
|
||||
if (path.extname(file).toLowerCase() === '.pem') {
|
||||
try {
|
||||
const pemFilePath = path.join(pemDirectory, file);
|
||||
const pemContent = fs.readFileSync(pemFilePath, 'utf8');
|
||||
const certificateData = parseCertificate(pemContent, file);
|
||||
|
||||
if (certificateData && certificateData.id) {
|
||||
const notAfterDate = new Date(certificateData.validity.notAfter);
|
||||
if (notAfterDate > new Date()) {
|
||||
batchData.push(prepareDataForInsertion(certificateData));
|
||||
|
||||
} else {
|
||||
console.log('\x1b[90m%s\x1b[0m', `certificate ${file} is expired.`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing file ${file}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (batchData.length > 0) {
|
||||
try {
|
||||
if (tableName === 'csca_masterlist') {
|
||||
await prisma.csca_masterlist.createMany({
|
||||
data: batchData,
|
||||
skipDuplicates: true,
|
||||
});
|
||||
} else {
|
||||
await prisma.dsc_masterlist.createMany({
|
||||
data: batchData,
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
console.log(`Successfully processed batch ${startIdx + 1}-${endIdx} (${batchData.length} certificates)`);
|
||||
} catch (error) {
|
||||
console.error(`Error inserting batch ${startIdx + 1}-${endIdx}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const prisma = getPrismaClientFromEnv();
|
||||
console.log(`Reading directory: ${pemDirectory}`);
|
||||
const files = fs.readdirSync(pemDirectory);
|
||||
console.log(`Found ${files.length} files`);
|
||||
const totalFiles = files.length;
|
||||
console.log(`Found ${totalFiles} files`);
|
||||
|
||||
const processedCertificates = new Set<string>();
|
||||
const BATCH_SIZE = 1000; // Adjust as needed
|
||||
const totalBatches = Math.ceil(totalFiles / BATCH_SIZE);
|
||||
|
||||
for (const file of files) {
|
||||
if (path.extname(file).toLowerCase() === '.pem') {
|
||||
console.log(`Processing file: ${file}`);
|
||||
const pemFilePath = path.join(pemDirectory, file);
|
||||
const pemContent = fs.readFileSync(pemFilePath, 'utf8');
|
||||
const certificateData = processCertificate(pemContent, file);
|
||||
if (certificateData && certificateData.id) {
|
||||
console.log(`Inserting certificate: ${certificateData.id}`);
|
||||
if (processedCertificates.has(certificateData.id)) {
|
||||
console.log(`Certificate with ID ${certificateData.id} has already been processed. Skipping.`);
|
||||
continue;
|
||||
}
|
||||
insertDB(prisma, tableName, certificateData);
|
||||
processedCertificates.add(certificateData.id);
|
||||
for (let i = 0; i < files.length; i += BATCH_SIZE) {
|
||||
const currentBatch = Math.floor(i / BATCH_SIZE) + 1;
|
||||
console.log(`Processing batch ${currentBatch}/${totalBatches} (${Math.min(BATCH_SIZE, totalFiles - i)} files)`);
|
||||
|
||||
}
|
||||
}
|
||||
await processBatch(files, prisma, i, BATCH_SIZE);
|
||||
|
||||
// Optional: Delay between batches
|
||||
// await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
// Log progress
|
||||
const progress = ((i + BATCH_SIZE) / totalFiles * 100).toFixed(2);
|
||||
console.log(`Progress: ${progress}%`);
|
||||
}
|
||||
|
||||
await prisma.$disconnect();
|
||||
console.log('Processing completed successfully');
|
||||
} catch (error) {
|
||||
console.error('Error in main:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Script started');
|
||||
main();
|
||||
main().catch(console.error);
|
||||
|
||||
@@ -38,6 +38,15 @@ export const standardCurves: StandardCurve[] = [
|
||||
h: "01"
|
||||
}
|
||||
,
|
||||
{
|
||||
name: "brainpoolP224r1",
|
||||
p: "d7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
|
||||
a: "68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
|
||||
b: "2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
|
||||
G: "040d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
|
||||
n: "d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
|
||||
h: "01"
|
||||
},
|
||||
{
|
||||
name: "brainpoolP256r1",
|
||||
p: "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
|
||||
@@ -93,23 +102,16 @@ export function identifyCurve(params: any): string {
|
||||
return curve.name;
|
||||
}
|
||||
}
|
||||
console.log("Unknown curve:", normalizedParams);
|
||||
return "Unknown curve";
|
||||
}
|
||||
|
||||
export function getNamedCurve(oid: string): string {
|
||||
const curves = {
|
||||
'1.2.840.10045.3.1.7': 'secp256r1',
|
||||
'1.3.132.0.34': 'secp384r1',
|
||||
'1.3.132.0.35': 'secp521r1',
|
||||
// Add more curve OIDs as needed
|
||||
};
|
||||
return curves[oid] || `Unknown (${oid})`;
|
||||
}
|
||||
export function getECDSACurveBits(curveName: string): string {
|
||||
const curveBits: { [key: string]: number } = {
|
||||
'secp256r1': 256,
|
||||
'secp384r1': 384,
|
||||
'secp521r1': 521,
|
||||
'brainpoolP224r1': 224,
|
||||
'brainpoolP256r1': 256,
|
||||
'brainpoolP384r1': 384,
|
||||
'brainpoolP512r1': 512,
|
||||
127
registry/src/utils/certificateParsing/oids.ts
Normal file
127
registry/src/utils/certificateParsing/oids.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
export const oidMap: { [key: string]: string } = {
|
||||
"1.2.840.113549.3.7": "3des",
|
||||
"2.16.840.1.101.3.4.1.2": "aes128",
|
||||
"2.16.840.1.101.3.4.1.5": "aes128wrap",
|
||||
"2.16.840.1.101.3.4.1.22": "aes192",
|
||||
"2.16.840.1.101.3.4.1.25": "aes192wrap",
|
||||
"2.16.840.1.101.3.4.1.42": "aes256",
|
||||
"2.16.840.1.101.3.4.1.45": "aes256wrap",
|
||||
"1.3.36.3.3.2.8.1.1.1": "brainpoolP160r1",
|
||||
"1.3.36.3.3.2.8.1.1.2": "brainpoolP160t1",
|
||||
"1.3.36.3.3.2.8.1.1.3": "brainpoolP192r1",
|
||||
"1.3.36.3.3.2.8.1.1.4": "brainpoolP192t1",
|
||||
"1.3.36.3.3.2.8.1.1.5": "brainpoolP224r1",
|
||||
"1.3.36.3.3.2.8.1.1.6": "brainpoolP224t1",
|
||||
"1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1",
|
||||
"1.3.36.3.3.2.8.1.1.8": "brainpoolP256t1",
|
||||
"1.3.36.3.3.2.8.1.1.9": "brainpoolP320r1",
|
||||
"1.3.36.3.3.2.8.1.1.10": "brainpoolP320t1",
|
||||
"1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1",
|
||||
"1.3.36.3.3.2.8.1.1.12": "brainpoolP384t1",
|
||||
"1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1",
|
||||
"1.3.36.3.3.2.8.1.1.14": "brainpoolP512t1",
|
||||
"2.5.4.6": "C",
|
||||
"1.2.840.113549.1.9.16.3.6": "CMS3DESwrap",
|
||||
"1.2.840.113549.1.9.16.3.7": "CMSRC2wrap",
|
||||
"2.5.4.3": "CN",
|
||||
"1.3.6.1.5.5.7.2.1": "CPS",
|
||||
"0.9.2342.19200300.100.1.25": "DC",
|
||||
"1.3.14.3.2.7": "des",
|
||||
"2.5.4.13": "Description",
|
||||
"1.2.840.10046.2.1": "DH",
|
||||
"2.5.4.46": "dnQualifier",
|
||||
"1.2.840.10040.4.1": "DSA",
|
||||
"1.3.14.3.2.27": "dsaSHA1",
|
||||
"1.2.840.113549.1.9.1": "E",
|
||||
"1.2.156.11235.1.1.2.1": "ec192wapi",
|
||||
"1.2.840.10045.2.1": "ECC",
|
||||
"1.3.133.16.840.63.0.2": "ECDH_STD_SHA1_KDF",
|
||||
"1.3.132.1.11.1": "ECDH_STD_SHA256_KDF",
|
||||
"1.3.132.1.11.2": "ECDH_STD_SHA384_KDF",
|
||||
"1.2.840.10045.3.1.7": "ECDSA_P256",
|
||||
"1.3.132.0.34": "ECDSA_P384",
|
||||
"1.3.132.0.35": "ECDSA_P521",
|
||||
"1.2.840.113549.1.9.16.3.5": "ESDH",
|
||||
"2.5.4.42": "G",
|
||||
"2.5.4.43": "I",
|
||||
"2.5.4.7": "L",
|
||||
"1.2.840.113549.2.2": "md2",
|
||||
"1.2.840.113549.1.1.2": "md2RSA",
|
||||
"1.2.840.113549.2.4": "md4",
|
||||
"1.2.840.113549.1.1.3": "md4RSA",
|
||||
"1.2.840.113549.2.5": "md5",
|
||||
"1.2.840.113549.1.1.4": "md5RSA",
|
||||
"1.2.840.113549.1.1.8": "mgf1",
|
||||
"2.16.840.1.101.2.1.1.20": "mosaicKMandUpdSig",
|
||||
"2.16.840.1.101.2.1.1.19": "mosaicUpdatedSig",
|
||||
"1.2.840.10045.3.1.1": "nistP192",
|
||||
"1.3.132.0.33": "nistP224",
|
||||
"1.3.6.1.5.5.7.6.2": "NO_SIGN",
|
||||
"2.5.4.10": "O",
|
||||
"2.5.4.11": "OU",
|
||||
"2.5.4.20": "Phone",
|
||||
"2.5.4.18": "POBox",
|
||||
"2.5.4.17": "PostalCode",
|
||||
"1.2.840.113549.3.2": "rc2",
|
||||
"1.2.840.113549.3.4": "rc4",
|
||||
"1.2.840.113549.1.1.1": "RSA",
|
||||
"1.2.840.113549.1.1.7": "RSAES_OAEP",
|
||||
"1.2.840.113549.1.1.10": "RSASSA_PSS",
|
||||
"2.5.4.8": "S",
|
||||
"1.3.132.0.9": "secP160k1",
|
||||
"1.3.132.0.8": "secP160r1",
|
||||
"1.3.132.0.30": "secP160r2",
|
||||
"1.3.132.0.31": "secP192k1",
|
||||
"1.3.132.0.32": "secP224k1",
|
||||
"1.3.132.0.10": "secP256k1",
|
||||
"2.5.4.5": "SERIALNUMBER",
|
||||
"1.3.14.3.2.26": "sha1",
|
||||
"1.2.840.10040.4.3": "sha1DSA",
|
||||
"1.2.840.10045.4.1": "sha1ECDSA",
|
||||
"1.2.840.113549.1.1.5": "sha1RSA",
|
||||
"2.16.840.1.101.3.4.2.1": "sha256",
|
||||
"1.2.840.10045.4.3.2": "sha256ECDSA",
|
||||
"1.2.840.113549.1.1.11": "sha256RSA",
|
||||
"2.16.840.1.101.3.4.2.2": "sha384",
|
||||
"1.2.840.10045.4.3.3": "sha384ECDSA",
|
||||
"1.2.840.113549.1.1.12": "sha384RSA",
|
||||
"2.16.840.1.101.3.4.2.3": "sha512",
|
||||
"1.2.840.10045.4.3.4": "sha512ECDSA",
|
||||
"1.2.840.113549.1.1.13": "sha512RSA",
|
||||
"2.5.4.4": "SN",
|
||||
"1.2.840.10045.4.3": "specifiedECDSA",
|
||||
"2.5.4.9": "STREET",
|
||||
"2.5.4.12": "T",
|
||||
"2.23.133.2.1": "TPMManufacturer",
|
||||
"2.23.133.2.2": "TPMModel",
|
||||
"2.23.133.2.3": "TPMVersion",
|
||||
"2.23.43.1.4.9": "wtls9",
|
||||
"2.5.4.24": "X21Address",
|
||||
"1.2.840.10045.3.1.2": "x962P192v2",
|
||||
"1.2.840.10045.3.1.3": "x962P192v3",
|
||||
"1.2.840.10045.3.1.4": "x962P239v1",
|
||||
"1.2.840.10045.3.1.5": "x962P239v2",
|
||||
"1.2.840.10045.3.1.6": "x962P239v3",
|
||||
};
|
||||
|
||||
export function getFriendlyName(oid: string): string {
|
||||
return oidMap[oid] || "Unknown Algorithm";
|
||||
}
|
||||
|
||||
export function extractHashFunction(friendlyName: string): string {
|
||||
if (friendlyName.toLowerCase().includes('sha1')) {
|
||||
return 'sha1'
|
||||
}
|
||||
if (friendlyName.toLowerCase().includes('sha256')) {
|
||||
return 'sha256'
|
||||
}
|
||||
if (friendlyName.toLowerCase().includes('sha384')) {
|
||||
return 'sha384'
|
||||
}
|
||||
if (friendlyName.toLowerCase().includes('sha512')) {
|
||||
return 'sha512'
|
||||
}
|
||||
throw new Error("hash function not found in: " + friendlyName);
|
||||
|
||||
return 'unknown'
|
||||
}
|
||||
202
registry/src/utils/certificateParsing/parseCertificate.ts
Normal file
202
registry/src/utils/certificateParsing/parseCertificate.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
import * as asn1js from "asn1js";
|
||||
import { Certificate, RSAPublicKey, RSASSAPSSParams } from "pkijs";
|
||||
import { extractHashFunction, getFriendlyName } from "./oids";
|
||||
import { CertificateData, PublicKeyDetailsECDSA, PublicKeyDetailsRSA, PublicKeyDetailsRSAPSS } from "./dataStructure";
|
||||
import { getECDSACurveBits, identifyCurve, StandardCurve } from "./curves";
|
||||
import { getIssuerCountryCode, getSubjectKeyIdentifier } from "./utils";
|
||||
import fs from 'fs';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
export function parseCertificate(pem: string, fileName: string): any {
|
||||
let certificateData: CertificateData = {
|
||||
id: '',
|
||||
issuer: '',
|
||||
validity: {
|
||||
notBefore: '',
|
||||
notAfter: ''
|
||||
},
|
||||
subjectKeyIdentifier: '',
|
||||
signatureAlgorithm: '',
|
||||
hashAlgorithm: '',
|
||||
publicKeyDetails: undefined,
|
||||
rawPem: '',
|
||||
rawTxt: ''
|
||||
};
|
||||
try {
|
||||
const pemFormatted = pem.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n|\r)/g, "");
|
||||
const binary = Buffer.from(pemFormatted, "base64");
|
||||
const arrayBuffer = new ArrayBuffer(binary.length);
|
||||
const view = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
view[i] = binary[i];
|
||||
}
|
||||
|
||||
const asn1 = asn1js.fromBER(arrayBuffer);
|
||||
if (asn1.offset === -1) {
|
||||
throw new Error(`ASN.1 parsing error: ${asn1.result.error}`);
|
||||
}
|
||||
|
||||
const cert = new Certificate({ schema: asn1.result });
|
||||
const publicKeyAlgoOID = cert.subjectPublicKeyInfo.algorithm.algorithmId;
|
||||
const publicKeyAlgoFN = getFriendlyName(publicKeyAlgoOID);
|
||||
const signatureAlgoOID = cert.signatureAlgorithm.algorithmId;
|
||||
const signatureAlgoFN = getFriendlyName(signatureAlgoOID);
|
||||
|
||||
|
||||
let params;
|
||||
if (publicKeyAlgoFN === 'RSA') {
|
||||
if (signatureAlgoFN === 'RSASSA_PSS') {
|
||||
certificateData.signatureAlgorithm = "rsapss";
|
||||
params = getParamsRSAPSS(cert);
|
||||
certificateData.hashAlgorithm = (params as PublicKeyDetailsRSAPSS).hashAlgorithm;
|
||||
}
|
||||
else {
|
||||
certificateData.hashAlgorithm = extractHashFunction(signatureAlgoFN);
|
||||
certificateData.signatureAlgorithm = "rsa";
|
||||
params = getParamsRSA(cert);
|
||||
}
|
||||
|
||||
}
|
||||
else if (publicKeyAlgoFN === 'ECC') {
|
||||
certificateData.hashAlgorithm = extractHashFunction(signatureAlgoFN);
|
||||
certificateData.signatureAlgorithm = "ecdsa";
|
||||
params = getParamsECDSA(cert);
|
||||
}
|
||||
else {
|
||||
console.log(publicKeyAlgoFN);
|
||||
}
|
||||
certificateData.publicKeyDetails = params;
|
||||
certificateData.issuer = getIssuerCountryCode(cert);;
|
||||
certificateData.validity = {
|
||||
notBefore: cert.notBefore.value.toString(),
|
||||
notAfter: cert.notAfter.value.toString()
|
||||
};
|
||||
const ski = getSubjectKeyIdentifier(cert);
|
||||
certificateData.id = ski.slice(0, 12);
|
||||
certificateData.subjectKeyIdentifier = ski;
|
||||
|
||||
certificateData.rawPem = pem;
|
||||
const tempCertPath = `/tmp/${fileName}.pem`;
|
||||
fs.writeFileSync(tempCertPath, pem);
|
||||
try {
|
||||
const openSslOutput = execSync(`openssl x509 -in ${tempCertPath} -text -noout`).toString();
|
||||
certificateData.rawTxt = openSslOutput;
|
||||
} catch (error) {
|
||||
console.error(`Error executing OpenSSL command: ${error}`);
|
||||
certificateData.rawTxt = 'Error: Unable to generate human-readable format';
|
||||
} finally {
|
||||
fs.unlinkSync(tempCertPath);
|
||||
}
|
||||
|
||||
|
||||
return certificateData;
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error processing certificate ${fileName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function getParamsRSA(cert: Certificate): PublicKeyDetailsRSA {
|
||||
const publicKeyValue = cert.subjectPublicKeyInfo.parsedKey as RSAPublicKey;
|
||||
const modulusBigInt = publicKeyValue.modulus.toBigInt();
|
||||
const modulusHex = modulusBigInt < 0n ? (-modulusBigInt).toString(16) : modulusBigInt.toString(16);
|
||||
const exponentBigInt = publicKeyValue.publicExponent.toBigInt();
|
||||
const exponentDecimal = exponentBigInt.toString();
|
||||
|
||||
const modulusBytes = publicKeyValue.modulus.valueBlock.valueHexView;
|
||||
const actualBits = modulusBytes.length * 8;
|
||||
|
||||
return {
|
||||
modulus: modulusHex,
|
||||
exponent: exponentDecimal,
|
||||
bits: actualBits.toString()
|
||||
};
|
||||
}
|
||||
|
||||
function getParamsRSAPSS(cert: Certificate): PublicKeyDetailsRSAPSS {
|
||||
const { modulus, exponent, bits } = getParamsRSA(cert);
|
||||
const sigAlgParams = cert.signatureAlgorithm.algorithmParams;
|
||||
const pssParams = new RSASSAPSSParams({ schema: sigAlgParams });
|
||||
const hashAlgorithm = getFriendlyName(pssParams.hashAlgorithm.algorithmId);
|
||||
const mgf = getFriendlyName(pssParams.maskGenAlgorithm.algorithmId);
|
||||
|
||||
return {
|
||||
modulus: modulus,
|
||||
exponent: exponent,
|
||||
bits: bits,
|
||||
hashAlgorithm: hashAlgorithm,
|
||||
mgf: mgf,
|
||||
saltLength: pssParams.saltLength.toString()
|
||||
};
|
||||
}
|
||||
|
||||
export function getParamsECDSA(cert: Certificate): PublicKeyDetailsECDSA {
|
||||
try {
|
||||
const algorithmParams = cert.subjectPublicKeyInfo.algorithm.algorithmParams;
|
||||
if (!algorithmParams) {
|
||||
console.log('No algorithm params found');
|
||||
return { curve: 'Unknown', params: {} as StandardCurve, bits: 'Unknown' };
|
||||
}
|
||||
|
||||
const params = asn1js.fromBER(algorithmParams.valueBeforeDecodeView).result;
|
||||
const valueBlock: any = params.valueBlock;
|
||||
|
||||
if (valueBlock.value && valueBlock.value.length >= 5) {
|
||||
const curveParams: StandardCurve = {} as StandardCurve;
|
||||
// Field ID (index 1)
|
||||
const fieldId = valueBlock.value[1];
|
||||
if (fieldId && fieldId.valueBlock && fieldId.valueBlock.value) {
|
||||
const fieldType = fieldId.valueBlock.value[0];
|
||||
const prime = fieldId.valueBlock.value[1];
|
||||
//curveParams.fieldType = fieldType.valueBlock.toString();
|
||||
curveParams.p = Buffer.from(prime.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
// Curve Coefficients (index 2)
|
||||
const curveCoefficients = valueBlock.value[2];
|
||||
if (curveCoefficients && curveCoefficients.valueBlock && curveCoefficients.valueBlock.value) {
|
||||
const a = curveCoefficients.valueBlock.value[0];
|
||||
const b = curveCoefficients.valueBlock.value[1];
|
||||
curveParams.a = Buffer.from(a.valueBlock.valueHexView).toString('hex');
|
||||
curveParams.b = Buffer.from(b.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
// Base Point G (index 3)
|
||||
const basePoint = valueBlock.value[3];
|
||||
if (basePoint && basePoint.valueBlock) {
|
||||
curveParams.G = Buffer.from(basePoint.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
// Order n (index 4)
|
||||
const order = valueBlock.value[4];
|
||||
if (order && order.valueBlock) {
|
||||
curveParams.n = Buffer.from(order.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
if (valueBlock.value.length >= 6) {
|
||||
// Cofactor h (index 5)
|
||||
const cofactor = valueBlock.value[5];
|
||||
if (cofactor && cofactor.valueBlock) {
|
||||
curveParams.h = Buffer.from(cofactor.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
}
|
||||
else {
|
||||
curveParams.h = '01';
|
||||
}
|
||||
|
||||
const identifiedCurve = identifyCurve(curveParams);
|
||||
return { curve: identifiedCurve, params: curveParams, bits: getECDSACurveBits(identifiedCurve) };
|
||||
} else {
|
||||
if (valueBlock.value) {
|
||||
console.log(valueBlock.value);
|
||||
}
|
||||
else {
|
||||
console.log('No value block found');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error parsing EC parameters:', error);
|
||||
return { curve: 'Error', params: {} as StandardCurve, bits: 'Unknown' };
|
||||
}
|
||||
}
|
||||
31
registry/src/utils/certificateParsing/utils.ts
Normal file
31
registry/src/utils/certificateParsing/utils.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Certificate } from "pkijs";
|
||||
|
||||
export const getSubjectKeyIdentifier = (cert: Certificate): string => {
|
||||
const subjectKeyIdentifier = cert.extensions.find(
|
||||
(ext) => ext.extnID === '2.5.29.14'
|
||||
);
|
||||
if (subjectKeyIdentifier) {
|
||||
let skiValue = Buffer.from(subjectKeyIdentifier.extnValue.valueBlock.valueHexView).toString('hex');
|
||||
|
||||
skiValue = skiValue.replace(/^(?:3016)?(?:0414)?/, '');
|
||||
return skiValue
|
||||
} else {
|
||||
// do a sha1 of the certificate tbs
|
||||
const crypto = require('crypto');
|
||||
const sha1 = crypto.createHash('sha1');
|
||||
sha1.update(cert.tbsView);
|
||||
return sha1.digest('hex');
|
||||
}
|
||||
}
|
||||
|
||||
export function getIssuerCountryCode(cert: Certificate): string {
|
||||
const issuerRDN = cert.issuer.typesAndValues;
|
||||
let issuerCountryCode = '';
|
||||
for (const rdn of issuerRDN) {
|
||||
if (rdn.type === '2.5.4.6') { // OID for Country Name
|
||||
issuerCountryCode = rdn.value.valueBlock.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return issuerCountryCode.toUpperCase();
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
import * as path from 'path';
|
||||
import jsrsasign from 'jsrsasign';
|
||||
import * as asn1 from 'asn1.js';
|
||||
import fs from 'fs';
|
||||
|
||||
|
||||
export const RSAPublicKey = asn1.define('RSAPublicKey', function () {
|
||||
this.seq().obj(
|
||||
this.key('n').int(),
|
||||
this.key('e').int()
|
||||
);
|
||||
});
|
||||
|
||||
export function isRsaPublicKey(key) {
|
||||
return key.type === 'RSA' || key.type === 'RSA-PSS';
|
||||
}
|
||||
|
||||
export function getPublicKey(certificate) {
|
||||
const publicKeyInfo = certificate.getPublicKeyHex();
|
||||
|
||||
try {
|
||||
// Try to parse the public key as ASN.1
|
||||
const publicKeyAsn1 = asn1.define('PublicKey', function () {
|
||||
this.seq().obj(
|
||||
this.key('algorithm').seq().obj(
|
||||
this.key('algorithmId').objid(),
|
||||
this.key('parameters').optional().any()
|
||||
),
|
||||
this.key('publicKey').bitstr()
|
||||
);
|
||||
});
|
||||
|
||||
const parsed = publicKeyAsn1.decode(Buffer.from(publicKeyInfo, 'hex'), 'der');
|
||||
const publicKeyBuffer = parsed.publicKey.data;
|
||||
|
||||
// Parse the RSA public key
|
||||
const rsaPublicKey = RSAPublicKey.decode(publicKeyBuffer, 'der');
|
||||
|
||||
return {
|
||||
n: new jsrsasign.BigInteger(rsaPublicKey.n.toString('hex'), 16),
|
||||
e: new jsrsasign.BigInteger(rsaPublicKey.e.toString('hex'), 16),
|
||||
type: 'RSA'
|
||||
};
|
||||
} catch (e) {
|
||||
console.error("Error parsing public key:", e);
|
||||
}
|
||||
|
||||
// If parsing fails, fall back to manual extraction
|
||||
const modulus = extractModulus(publicKeyInfo);
|
||||
if (modulus) {
|
||||
return { n: new jsrsasign.BigInteger(modulus, 16), type: 'RSA' };
|
||||
}
|
||||
|
||||
throw new Error("Unable to extract public key");
|
||||
}
|
||||
|
||||
function extractModulus(publicKeyInfo: string): string | null {
|
||||
// RSA OID
|
||||
const rsaOid = '2a864886f70d010101';
|
||||
// RSA-PSS OID
|
||||
const rsaPssOid = '2a864886f70d01010a';
|
||||
|
||||
let offset = publicKeyInfo.indexOf(rsaOid);
|
||||
if (offset === -1) {
|
||||
offset = publicKeyInfo.indexOf(rsaPssOid);
|
||||
}
|
||||
|
||||
if (offset === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip OID and move to the bit string
|
||||
offset = publicKeyInfo.indexOf('03', offset);
|
||||
if (offset === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip bit string tag and length
|
||||
offset += 4;
|
||||
|
||||
// Extract modulus
|
||||
const modulusStart = publicKeyInfo.indexOf('02', offset) + 2;
|
||||
const modulusLength = parseInt(publicKeyInfo.substr(modulusStart, 2), 16) * 2;
|
||||
const modulus = publicKeyInfo.substr(modulusStart + 2, modulusLength);
|
||||
|
||||
return modulus;
|
||||
}
|
||||
|
||||
export function readCertificate(filePath: string): jsrsasign.X509 {
|
||||
const certPem = fs.readFileSync(filePath, 'utf8');
|
||||
const certificate = new jsrsasign.X509();
|
||||
certificate.readCertPEM(certPem);
|
||||
return certificate;
|
||||
}
|
||||
|
||||
export function getTBSCertificate(certificate: jsrsasign.X509): Buffer {
|
||||
// console.log("Certificate:", certificate);
|
||||
|
||||
const certASN1 = certificate.getParam();
|
||||
// console.log("certASN1:", certASN1);
|
||||
|
||||
if (!certASN1) {
|
||||
console.error("Failed to get certificate parameters");
|
||||
throw new Error("Invalid certificate structure");
|
||||
}
|
||||
|
||||
// Extract the TBS part directly from the certificate's hex representation
|
||||
const certHex = certificate.hex;
|
||||
const tbsStartIndex = certHex.indexOf('30') + 2; // Start after the first sequence tag
|
||||
const tbsLength = parseInt(certHex.substr(tbsStartIndex, 2), 16) * 2 + 2; // Length in bytes * 2 for hex + 2 for length field
|
||||
const tbsHex = certHex.substr(tbsStartIndex - 2, tbsLength); // Include the sequence tag
|
||||
|
||||
// console.log("TBS Hex:", tbsHex);
|
||||
|
||||
return Buffer.from(tbsHex, 'hex');
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { processCertificate } from './utils';
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
import { CertificateData, PublicKeyDetailsRSA, PublicKeyDetailsECDSA } from "./dataStructure";
|
||||
import { mock_csca_sha1_rsa_4096, mock_csca_sha256_rsa_4096, mock_csca_sha256_rsapss_4096 } from '../../../common/src/constants/mockCertificates';
|
||||
|
||||
export function getListOfExponents(certificates: { [key: string]: CertificateData }) {
|
||||
let exponents: string[] = [];
|
||||
for (const certificate of Object.values(certificates)) {
|
||||
if (certificate.signatureAlgorithm === "rsa" || certificate.signatureAlgorithm === "rsa-pss") {
|
||||
if (!certificate.publicKeyDetails) {
|
||||
console.log(`\x1b[31m${certificate.id} has no public key details\x1b[0m`);
|
||||
// console.log(certificate);
|
||||
} else if ((certificate.publicKeyDetails as PublicKeyDetailsRSA).exponent) {
|
||||
// check if the exponent is not already in the list
|
||||
if (!exponents.includes((certificate.publicKeyDetails as PublicKeyDetailsRSA).exponent)) {
|
||||
exponents.push((certificate.publicKeyDetails as PublicKeyDetailsRSA).exponent);
|
||||
}
|
||||
if ((certificate.publicKeyDetails as PublicKeyDetailsRSA).exponent != "65537") {
|
||||
console.log(`\x1b[31m${certificate.id} with exponent ${(certificate.publicKeyDetails as PublicKeyDetailsRSA).exponent}\x1b[0m`);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// order the exponents in ascending order
|
||||
exponents.sort((a, b) => parseInt(a) - parseInt(b));
|
||||
return exponents;
|
||||
}
|
||||
|
||||
export async function getMapJson(certificates: { [key: string]: CertificateData }) {
|
||||
const certificateMap: { [key: string]: { [key: string]: number } } = {};
|
||||
|
||||
for (const certificateData of Object.values(certificates)) {
|
||||
const mapKey = getMapKey(certificateData);
|
||||
|
||||
if (!certificateMap[mapKey]) {
|
||||
certificateMap[mapKey] = {};
|
||||
}
|
||||
|
||||
if (!certificateMap[mapKey][certificateData.issuer]) {
|
||||
certificateMap[mapKey][certificateData.issuer] = 0;
|
||||
}
|
||||
|
||||
certificateMap[mapKey][certificateData.issuer]++;
|
||||
}
|
||||
return certificateMap;
|
||||
|
||||
}
|
||||
|
||||
function getMapKey(certificateData: CertificateData): string {
|
||||
const { signatureAlgorithm, hashAlgorithm, publicKeyDetails } = certificateData;
|
||||
|
||||
let keyDetails = 'unknown';
|
||||
|
||||
if (publicKeyDetails) {
|
||||
if (signatureAlgorithm === "ecdsa") {
|
||||
// ECDSA
|
||||
const curve = (publicKeyDetails as PublicKeyDetailsECDSA).curve;
|
||||
const keySize = (publicKeyDetails as PublicKeyDetailsRSA).bits.toString();
|
||||
|
||||
keyDetails = `${keySize} bit ${curve}`;
|
||||
} else {
|
||||
// RSA
|
||||
const keySize = (publicKeyDetails as PublicKeyDetailsRSA).bits.toString();
|
||||
const exponent = (publicKeyDetails as PublicKeyDetailsRSA).exponent;
|
||||
keyDetails = `${keySize} bit ${exponent}`;
|
||||
}
|
||||
}
|
||||
|
||||
return `${hashAlgorithm.toLowerCase()} ${signatureAlgorithm.toLowerCase()} ${keyDetails}`;
|
||||
}
|
||||
|
||||
export async function getSkiPemJson(certificates: { [key: string]: CertificateData }) {
|
||||
|
||||
const skiPemMap: { [ski: string]: string } = {};
|
||||
|
||||
for (const certificateData of Object.values(certificates)) {
|
||||
if (certificateData.rawPem) {
|
||||
skiPemMap[certificateData.subjectKeyIdentifier] = certificateData.rawPem;
|
||||
}
|
||||
}
|
||||
|
||||
return skiPemMap;
|
||||
}
|
||||
|
||||
export async function getRegistryJson(certificates: { [key: string]: CertificateData }) {
|
||||
|
||||
const certificateMap: { [id: string]: any } = {};
|
||||
|
||||
for (const certificateData of Object.values(certificates)) {
|
||||
if (certificateData.rawPem) {
|
||||
certificateMap[certificateData.id] = certificateData;
|
||||
}
|
||||
}
|
||||
return certificateMap;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { CertificateData, PublicKeyDetailsRSA, PublicKeyDetailsECDSA } from './utils';
|
||||
import { CertificateData, PublicKeyDetailsRSA, PublicKeyDetailsECDSA, PublicKeyDetailsRSAPSS } from './certificateParsing/dataStructure';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// Load environment variables
|
||||
@@ -39,39 +39,70 @@ function publicKeyDetailsToJson(details: PublicKeyDetailsRSA | PublicKeyDetailsE
|
||||
}
|
||||
|
||||
|
||||
export async function insertDB(prisma: PrismaClient, tableName: 'csca_masterlist' | 'dsc_masterlist', certificateData: CertificateData) {
|
||||
export async function insertDB(prisma: PrismaClient, tableName: 'csca_masterlist' | 'dsc_masterlist', data: CertificateData) {
|
||||
// Create a properly formatted data object for Prisma
|
||||
const flattenedData = {
|
||||
id: data.id,
|
||||
issuer: data.issuer,
|
||||
hashAlgorithm: data.hashAlgorithm,
|
||||
signatureAlgorithm: data.signatureAlgorithm,
|
||||
// Convert JSON objects to strings
|
||||
validity: JSON.stringify(data.validity),
|
||||
publicKeyDetails: JSON.stringify(data.publicKeyDetails),
|
||||
subjectKeyIdentifier: data.subjectKeyIdentifier,
|
||||
rawPem: data.rawPem,
|
||||
rawTxt: data.rawTxt,
|
||||
|
||||
// Flattened fields from publicKeyDetails
|
||||
pk_modulus: data.publicKeyDetails?.['modulus']?.toString() || null,
|
||||
pk_exponent: data.publicKeyDetails?.['exponent']?.toString() || null,
|
||||
pk_bits: data.publicKeyDetails?.['bits']?.toString() || null,
|
||||
pk_curve: (data.publicKeyDetails as PublicKeyDetailsECDSA)?.['curve']?.toString() || null,
|
||||
pk_hashAlgorithm: (data.publicKeyDetails as PublicKeyDetailsRSAPSS)?.['hashAlgorithm']?.toString() || null,
|
||||
pk_mgf: (data.publicKeyDetails as PublicKeyDetailsRSAPSS)?.['mgf']?.toString() || null,
|
||||
pk_saltLength: (data.publicKeyDetails as PublicKeyDetailsRSAPSS)?.['saltLength']?.toString() || null,
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
const result = await (prisma[tableName] as any).upsert({
|
||||
where: { id: certificateData.id },
|
||||
update: {
|
||||
// Overwrite all fields with new data
|
||||
issuer: certificateData.issuer,
|
||||
validity: certificateData.validity,
|
||||
subjectKeyIdentifier: certificateData.subjectKeyIdentifier,
|
||||
signatureAlgorithm: certificateData.signatureAlgorithm,
|
||||
hashAlgorithm: certificateData.hashAlgorithm,
|
||||
publicKeyDetails: publicKeyDetailsToJson(certificateData.publicKeyDetails),
|
||||
rawPem: certificateData.rawPem,
|
||||
rawTxt: certificateData.rawTxt,
|
||||
},
|
||||
create: {
|
||||
id: certificateData.id,
|
||||
issuer: certificateData.issuer,
|
||||
validity: certificateData.validity,
|
||||
subjectKeyIdentifier: certificateData.subjectKeyIdentifier,
|
||||
signatureAlgorithm: certificateData.signatureAlgorithm,
|
||||
hashAlgorithm: certificateData.hashAlgorithm,
|
||||
publicKeyDetails: publicKeyDetailsToJson(certificateData.publicKeyDetails),
|
||||
rawPem: certificateData.rawPem,
|
||||
rawTxt: certificateData.rawTxt,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Certificate with ID ${certificateData.id} has been upserted.`);
|
||||
return result;
|
||||
if (tableName === 'csca_masterlist') {
|
||||
await prisma.csca_masterlist.upsert({
|
||||
where: { id: data.id },
|
||||
update: flattenedData,
|
||||
create: flattenedData,
|
||||
});
|
||||
} else {
|
||||
await prisma.dsc_masterlist.upsert({
|
||||
where: { id: data.id },
|
||||
update: flattenedData,
|
||||
create: flattenedData,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error inserting certificate:', error);
|
||||
console.error('Error inserting data:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
// registry/src/utils/prisma.ts
|
||||
export function prepareDataForInsertion(data: CertificateData) {
|
||||
// Flatten the data as before
|
||||
const flattenedData = {
|
||||
id: data.id,
|
||||
issuer: data.issuer,
|
||||
hashAlgorithm: data.hashAlgorithm,
|
||||
signatureAlgorithm: data.signatureAlgorithm,
|
||||
validity: data.validity, // Assuming validity is serialized as JSON string
|
||||
publicKeyDetails: data.publicKeyDetails, // Assuming this is serialized as JSON string
|
||||
subjectKeyIdentifier: data.subjectKeyIdentifier,
|
||||
rawPem: data.rawPem,
|
||||
rawTxt: data.rawTxt,
|
||||
pk_modulus: data.publicKeyDetails?.['modulus']?.toString() || null,
|
||||
pk_exponent: data.publicKeyDetails?.['exponent']?.toString() || null,
|
||||
pk_bits: data.publicKeyDetails?.['bits']?.toString() || null,
|
||||
pk_curve: (data.publicKeyDetails as PublicKeyDetailsECDSA)?.['curve']?.toString() || null,
|
||||
pk_hashAlgorithm: (data.publicKeyDetails as PublicKeyDetailsRSAPSS)?.['hashAlgorithm']?.toString() || null,
|
||||
pk_mgf: (data.publicKeyDetails as PublicKeyDetailsRSAPSS)?.['mgf']?.toString() || null,
|
||||
pk_saltLength: (data.publicKeyDetails as PublicKeyDetailsRSAPSS)?.['saltLength']?.toString() || null,
|
||||
};
|
||||
|
||||
return flattenedData;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import * as fs from 'fs';
|
||||
import { CertificateData, PublicKeyDetailsRSAPSS } from './dataStructure';
|
||||
import { parseRsaPssPublicKey, parseECParameters, parseRsaPublicKey } from './publicKeyDetails';
|
||||
import { getCertificateFromPem, getIssuerCountryCode, getSignatureAlgorithmDetails, getSubjectKeyIdentifier } from './utils';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
export function processCertificate(pemContent: string, fileName: string): CertificateData {
|
||||
let certificateData: CertificateData = {
|
||||
id: '',
|
||||
issuer: '',
|
||||
validity: {
|
||||
notBefore: '',
|
||||
notAfter: ''
|
||||
},
|
||||
subjectKeyIdentifier: '',
|
||||
signatureAlgorithm: '',
|
||||
hashAlgorithm: '',
|
||||
publicKeyDetails: undefined,
|
||||
rawPem: '',
|
||||
rawTxt: ''
|
||||
};
|
||||
|
||||
const cert = getCertificateFromPem(pemContent);
|
||||
const sbk = getSubjectKeyIdentifier(cert);
|
||||
certificateData.id = sbk.slice(0, 12);
|
||||
certificateData.subjectKeyIdentifier = sbk;
|
||||
certificateData.issuer = getIssuerCountryCode(cert);;
|
||||
certificateData.validity = {
|
||||
notBefore: cert.notBefore.value.toString(),
|
||||
notAfter: cert.notAfter.value.toString()
|
||||
};
|
||||
|
||||
const { signatureAlgorithm, hashAlgorithm } = getSignatureAlgorithmDetails(cert.signatureAlgorithm.algorithmId);
|
||||
certificateData.signatureAlgorithm = signatureAlgorithm;
|
||||
certificateData.hashAlgorithm = hashAlgorithm;
|
||||
const subjectPublicKeyInfo = cert.subjectPublicKeyInfo;
|
||||
switch (signatureAlgorithm) {
|
||||
case 'rsa':
|
||||
certificateData.publicKeyDetails = parseRsaPublicKey(subjectPublicKeyInfo);
|
||||
if (!certificateData.publicKeyDetails) {
|
||||
console.log('\x1b[33mRSA public key not found, probably ECDSA certificate\x1b[0m');
|
||||
}
|
||||
break;
|
||||
case 'rsa-pss':
|
||||
const rsaPssParams = cert.signatureAlgorithm.algorithmParams;
|
||||
certificateData.publicKeyDetails = parseRsaPssPublicKey(subjectPublicKeyInfo, rsaPssParams);
|
||||
if (certificateData.publicKeyDetails) {
|
||||
certificateData.hashAlgorithm = (certificateData.publicKeyDetails as PublicKeyDetailsRSAPSS).hashAlgorithm;
|
||||
}
|
||||
if (!certificateData.publicKeyDetails) {
|
||||
console.log('\x1b[33mRSA-PSS public key not found\x1b[0m');
|
||||
}
|
||||
break;
|
||||
case 'ecdsa':
|
||||
certificateData.publicKeyDetails = parseECParameters(subjectPublicKeyInfo);
|
||||
if (!certificateData.publicKeyDetails) {
|
||||
console.log('\x1b[33mECDSA public key not found\x1b[0m');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log('\x1b[33mUnknown signature algorithm: \x1b[0m', signatureAlgorithm);
|
||||
}
|
||||
|
||||
certificateData.rawPem = pemContent;
|
||||
const tempCertPath = `/tmp/${fileName}.pem`;
|
||||
fs.writeFileSync(tempCertPath, pemContent);
|
||||
try {
|
||||
const openSslOutput = execSync(`openssl x509 -in ${tempCertPath} -text -noout`).toString();
|
||||
certificateData.rawTxt = openSslOutput;
|
||||
} catch (error) {
|
||||
console.error(`Error executing OpenSSL command: ${error}`);
|
||||
certificateData.rawTxt = 'Error: Unable to generate human-readable format';
|
||||
} finally {
|
||||
fs.unlinkSync(tempCertPath);
|
||||
}
|
||||
|
||||
|
||||
if (certificateData.signatureAlgorithm === 'rsa-pss' && !certificateData.publicKeyDetails) {
|
||||
console.log('\x1b[33mRSA-PSS public key details not found in rssa-pss file: \x1b[0m', fileName);
|
||||
}
|
||||
return certificateData;
|
||||
}
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
import { fromBER, BitString } from 'asn1js';
|
||||
import * as asn1 from 'asn1js';
|
||||
import * as forge from 'node-forge';
|
||||
import { PublicKeyDetailsECDSA, PublicKeyDetailsRSA, PublicKeyDetailsRSAPSS } from './dataStructure';
|
||||
import { identifyCurve, StandardCurve, getNamedCurve, getECDSACurveBits } from './curves';
|
||||
import { getHashAlgorithmName } from './utils';
|
||||
|
||||
export function parseRsaPublicKey(subjectPublicKeyInfo: any): PublicKeyDetailsRSA {
|
||||
const publicKey = subjectPublicKeyInfo.subjectPublicKey;
|
||||
const asn1PublicKey = fromBER(publicKey.valueBlock.valueHexView);
|
||||
const rsaPublicKey = asn1PublicKey.result.valueBlock;
|
||||
|
||||
if (rsaPublicKey && (rsaPublicKey as any).value && (rsaPublicKey as any).value[0] && (rsaPublicKey as any).value[1]) {
|
||||
const modulusAsn1 = (rsaPublicKey as any).value[0];
|
||||
const exponentAsn1 = (rsaPublicKey as any).value[1];
|
||||
const modulusHex = Buffer.from(modulusAsn1.valueBlock.valueHexView).toString('hex');
|
||||
const exponentHex = Buffer.from(exponentAsn1.valueBlock.valueHexView).toString('hex');
|
||||
|
||||
const publicKeyForge = forge.pki.rsa.setPublicKey(
|
||||
new forge.jsbn.BigInteger(modulusHex, 16),
|
||||
new forge.jsbn.BigInteger(exponentHex, 16)
|
||||
);
|
||||
const publicKeyDetailsRSA: PublicKeyDetailsRSA = {
|
||||
modulus: publicKeyForge.n.toString(16),
|
||||
exponent: publicKeyForge.e.toString(10),
|
||||
bits: publicKeyForge.n.bitLength().toString()
|
||||
};
|
||||
return publicKeyDetailsRSA;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseECParameters(publicKeyInfo: any): PublicKeyDetailsECDSA {
|
||||
try {
|
||||
const algorithmParams = publicKeyInfo.algorithm.algorithmParams;
|
||||
if (!algorithmParams) {
|
||||
console.log('No algorithm params found');
|
||||
return { curve: 'Unknown', params: {} as StandardCurve, bits: 'Unknown' };
|
||||
}
|
||||
|
||||
const params = asn1.fromBER(algorithmParams.valueBeforeDecodeView).result;
|
||||
const valueBlock: any = params.valueBlock;
|
||||
|
||||
if (valueBlock.value && valueBlock.value.length >= 6) {
|
||||
const curveParams: StandardCurve = {} as StandardCurve;
|
||||
// Field ID (index 1)
|
||||
const fieldId = valueBlock.value[1];
|
||||
if (fieldId && fieldId.valueBlock && fieldId.valueBlock.value) {
|
||||
const fieldType = fieldId.valueBlock.value[0];
|
||||
const prime = fieldId.valueBlock.value[1];
|
||||
//curveParams.fieldType = fieldType.valueBlock.toString();
|
||||
curveParams.p = Buffer.from(prime.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
// Curve Coefficients (index 2)
|
||||
const curveCoefficients = valueBlock.value[2];
|
||||
if (curveCoefficients && curveCoefficients.valueBlock && curveCoefficients.valueBlock.value) {
|
||||
const a = curveCoefficients.valueBlock.value[0];
|
||||
const b = curveCoefficients.valueBlock.value[1];
|
||||
curveParams.a = Buffer.from(a.valueBlock.valueHexView).toString('hex');
|
||||
curveParams.b = Buffer.from(b.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
// Base Point G (index 3)
|
||||
const basePoint = valueBlock.value[3];
|
||||
if (basePoint && basePoint.valueBlock) {
|
||||
curveParams.G = Buffer.from(basePoint.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
// Order n (index 4)
|
||||
const order = valueBlock.value[4];
|
||||
if (order && order.valueBlock) {
|
||||
curveParams.n = Buffer.from(order.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
// Cofactor h (index 5)
|
||||
const cofactor = valueBlock.value[5];
|
||||
if (cofactor && cofactor.valueBlock) {
|
||||
curveParams.h = Buffer.from(cofactor.valueBlock.valueHexView).toString('hex');
|
||||
}
|
||||
|
||||
const identifiedCurve = identifyCurve(curveParams);
|
||||
return { curve: identifiedCurve, params: curveParams, bits: getECDSACurveBits(identifiedCurve) };
|
||||
} else {
|
||||
if (valueBlock.value) {
|
||||
|
||||
if (algorithmParams.idBlock.tagNumber === 6) {
|
||||
console.log('\x1b[33malgorithmParams.idBlock.tagNumber === 6, looking for algorithmParams.valueBlock\x1b[0m');
|
||||
|
||||
const curveOid = algorithmParams.valueBlock.toString();
|
||||
const curveName = getNamedCurve(curveOid);
|
||||
// console.error('\x1b[33mCurve OID:', curveName, '\x1b[0m');
|
||||
return { curve: curveName, params: {} as StandardCurve, bits: getECDSACurveBits(curveName) };
|
||||
}
|
||||
else {
|
||||
console.log('\x1b[31malgorithmParams.idBlock.tagNumber !== 6\x1b[0m');
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error('\x1b[31mvalue block is not defined\x1b[0m');
|
||||
}
|
||||
return { curve: 'Unknown', params: {} as StandardCurve, bits: 'Unknown' };
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error parsing EC parameters:', error);
|
||||
return { curve: 'Error', params: {} as StandardCurve, bits: 'Unknown' };
|
||||
}
|
||||
}
|
||||
|
||||
export function parseRsaPssParams(params: any): { hashAlgorithm: string, mgf: string, saltLength: string } {
|
||||
try {
|
||||
const algorithmParams = asn1.fromBER(params.valueBeforeDecodeView);
|
||||
const sequence = algorithmParams.result;
|
||||
|
||||
let hashAlgorithm = 'Unknown';
|
||||
let mgf = 'Unknown';
|
||||
let saltLength = "Unknown";
|
||||
|
||||
// Parse hash algorithm
|
||||
if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[0]) {
|
||||
const hashAlgorithmSequence = (sequence.valueBlock as any).value[0].valueBlock.value[0];
|
||||
const hashAlgorithmOid = hashAlgorithmSequence.valueBlock.value[0].valueBlock.toString();
|
||||
hashAlgorithm = getHashAlgorithmName(hashAlgorithmOid);
|
||||
}
|
||||
|
||||
// Parse MGF
|
||||
if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[1]) {
|
||||
const mgfSequence = (sequence.valueBlock as any).value[1].valueBlock.value[0];
|
||||
const mgfOid = mgfSequence.valueBlock.value[0].valueBlock.toString();
|
||||
mgf = mgfOid === '1.2.840.113549.1.1.8' ? 'MGF1' : `Unknown (${mgfOid})`;
|
||||
}
|
||||
// console.log((sequence.valueBlock as any).value[0].valueBlock);
|
||||
// console.log((sequence.valueBlock as any).value[1].valueBlock);
|
||||
// console.log((sequence.valueBlock as any).value[2].valueBlock);
|
||||
|
||||
// Parse salt length
|
||||
if ((sequence.valueBlock as any).value && (sequence.valueBlock as any).value[2]) {
|
||||
const saltLengthContainer = (sequence.valueBlock as any).value[2];
|
||||
|
||||
if (saltLengthContainer.valueBlock && saltLengthContainer.valueBlock.value) {
|
||||
const rawSaltLength = saltLengthContainer.valueBlock.value[0];
|
||||
if (typeof rawSaltLength === 'number') {
|
||||
saltLength = rawSaltLength.toString();
|
||||
|
||||
} else if (rawSaltLength && rawSaltLength.valueBlock && rawSaltLength.valueBlock.valueHexView) {
|
||||
const saltLengthValue = rawSaltLength.valueBlock.valueHexView[0];
|
||||
saltLength = saltLengthValue.toString();
|
||||
} else {
|
||||
console.error('\x1b[31mUnable to parse salt length\x1b[0m');
|
||||
}
|
||||
} else {
|
||||
console.log("\x1b[31mSalt length not found\x1b[0m");
|
||||
}
|
||||
}
|
||||
|
||||
return { hashAlgorithm, mgf, saltLength };
|
||||
} catch (error) {
|
||||
console.error('Error parsing RSA-PSS parameters:', error);
|
||||
return { hashAlgorithm: 'Unknown', mgf: 'Unknown', saltLength: "Unknown" };
|
||||
}
|
||||
}
|
||||
|
||||
export function parseRsaPssPublicKey(subjectPublicKeyInfo: any, rsaPssParams: any): PublicKeyDetailsRSAPSS {
|
||||
let hashAlgorithm = 'Unknown';
|
||||
let mgf = 'Unknown';
|
||||
let saltLength = "Unknown";
|
||||
|
||||
if (rsaPssParams) {
|
||||
const parsedParams = parseRsaPssParams(rsaPssParams);
|
||||
hashAlgorithm = parsedParams.hashAlgorithm;
|
||||
mgf = parsedParams.mgf;
|
||||
saltLength = parsedParams.saltLength;
|
||||
} else {
|
||||
console.log('\x1b[31mRSA-PSS parameters not found\x1b[0m');
|
||||
}
|
||||
|
||||
// Add PublicKeyDetails for RSA-PSS
|
||||
const publicKey = subjectPublicKeyInfo.subjectPublicKey;
|
||||
const asn1PublicKey = fromBER(publicKey.valueBlock.valueHexView);
|
||||
const rsaPublicKey = asn1PublicKey.result.valueBlock;
|
||||
|
||||
if (rsaPublicKey && (rsaPublicKey as any).value && (rsaPublicKey as any).value[0] && (rsaPublicKey as any).value[1]) {
|
||||
const modulusAsn1 = (rsaPublicKey as any).value[0];
|
||||
const exponentAsn1 = (rsaPublicKey as any).value[1];
|
||||
const modulusHex = Buffer.from(modulusAsn1.valueBlock.valueHexView).toString('hex');
|
||||
const exponentHex = Buffer.from(exponentAsn1.valueBlock.valueHexView).toString('hex');
|
||||
|
||||
const publicKeyForge = forge.pki.rsa.setPublicKey(
|
||||
new forge.jsbn.BigInteger(modulusHex, 16),
|
||||
new forge.jsbn.BigInteger(exponentHex, 16)
|
||||
);
|
||||
const PublicKeyDetailsRSAPSS: PublicKeyDetailsRSAPSS = {
|
||||
modulus: publicKeyForge.n.toString(16),
|
||||
exponent: publicKeyForge.e.toString(10),
|
||||
bits: publicKeyForge.n.bitLength().toString(),
|
||||
hashAlgorithm,
|
||||
mgf,
|
||||
saltLength
|
||||
};
|
||||
return PublicKeyDetailsRSAPSS;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
|
||||
import * as asn1 from 'asn1js';
|
||||
import { getNamedCurve, identifyCurve, StandardCurve } from './curves';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { Certificate } from 'pkijs';
|
||||
|
||||
export function getSignatureAlgorithmDetails(oid: string): { signatureAlgorithm: 'rsa' | 'ecdsa' | 'rsa-pss' | 'Unknown', hashAlgorithm: string } {
|
||||
const details = {
|
||||
'1.2.840.113549.1.1.5': { signatureAlgorithm: 'rsa', hashAlgorithm: 'sha1' },
|
||||
'1.2.840.113549.1.1.11': { signatureAlgorithm: 'rsa', hashAlgorithm: 'sha256' },
|
||||
'1.2.840.113549.1.1.12': { signatureAlgorithm: 'rsa', hashAlgorithm: 'sha384' },
|
||||
'1.2.840.113549.1.1.13': { signatureAlgorithm: 'rsa', hashAlgorithm: 'sha512' },
|
||||
// rsapss
|
||||
'1.2.840.113549.1.1.10': { signatureAlgorithm: 'rsa-pss', hashAlgorithm: 'variable' },
|
||||
// ecdsa
|
||||
'1.2.840.10045.4.1': { signatureAlgorithm: 'ecdsa', hashAlgorithm: 'sha1' },
|
||||
'1.2.840.10045.4.3.1': { signatureAlgorithm: 'ecdsa', hashAlgorithm: 'sha224' },
|
||||
'1.2.840.10045.4.3.2': { signatureAlgorithm: 'ecdsa', hashAlgorithm: 'sha256' },
|
||||
'1.2.840.10045.4.3.3': { signatureAlgorithm: 'ecdsa', hashAlgorithm: 'sha384' },
|
||||
'1.2.840.10045.4.3.4': { signatureAlgorithm: 'ecdsa', hashAlgorithm: 'sha512' },
|
||||
};
|
||||
return details[oid] || { signatureAlgorithm: `Unknown (${oid})`, hashAlgorithm: 'Unknown' };
|
||||
}
|
||||
export function getHashAlgorithmName(oid: string): string {
|
||||
const hashAlgorithms = {
|
||||
'1.3.14.3.2.26': 'sha1',
|
||||
'2.16.840.1.101.3.4.2.1': 'sha256',
|
||||
'2.16.840.1.101.3.4.2.2': 'sha384',
|
||||
'2.16.840.1.101.3.4.2.3': 'sha512',
|
||||
};
|
||||
return hashAlgorithms[oid] || `Unknown (${oid})`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function getCertificateFromPem(pemContent: string): Certificate {
|
||||
const certBuffer = Buffer.from(pemContent.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''), 'base64');
|
||||
const asn1Data = asn1.fromBER(certBuffer);
|
||||
return new Certificate({ schema: asn1Data.result });
|
||||
}
|
||||
|
||||
export const getSubjectKeyIdentifier = (cert: Certificate): string => {
|
||||
const subjectKeyIdentifier = cert.extensions.find(
|
||||
(ext) => ext.extnID === '2.5.29.14' // OID for Subject Key Identifier
|
||||
);
|
||||
if (subjectKeyIdentifier) {
|
||||
let skiValue = Buffer.from(subjectKeyIdentifier.extnValue.valueBlock.valueHexView).toString('hex');
|
||||
|
||||
skiValue = skiValue.replace(/^(?:3016)?(?:0414)?/, '');
|
||||
return skiValue
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function getIssuerCountryCode(cert: Certificate): string {
|
||||
const issuerRDN = cert.issuer.typesAndValues;
|
||||
let issuerCountryCode = '';
|
||||
for (const rdn of issuerRDN) {
|
||||
if (rdn.type === '2.5.4.6') { // OID for Country Name
|
||||
issuerCountryCode = rdn.value.valueBlock.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return issuerCountryCode.toUpperCase();
|
||||
}
|
||||
1639
registry/yarn.lock
1639
registry/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@openpassport/core",
|
||||
"version": "0.0.9",
|
||||
"version": "0.0.11",
|
||||
"main": "dist/sdk/core/index.js",
|
||||
"types": "dist/sdk/core/index.d.ts",
|
||||
"license": "MIT",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
sdk/qrcode/.yarn/install-state.gz
Normal file
BIN
sdk/qrcode/.yarn/install-state.gz
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@openpassport/qrcode",
|
||||
"version": "0.0.12",
|
||||
"version": "0.0.14",
|
||||
"main": "dist/sdk/qrcode/index.js",
|
||||
"types": "dist/sdk/qrcode/index.d.ts",
|
||||
"license": "MIT",
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
"author": "turnoffthiscomputer",
|
||||
"dependencies": {
|
||||
"@openpassport/core": "0.0.9",
|
||||
"@openpassport/core": "0.0.11",
|
||||
"@types/react": "^18.3.4",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/uuid": "^10.0.0",
|
||||
@@ -84,4 +84,4 @@
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ const handleWebSocketMessage =
|
||||
sessionId,
|
||||
proofVerified: local_proofVerified.toString(),
|
||||
});
|
||||
if (local_proofVerified) {
|
||||
if (local_proofVerified.valid) {
|
||||
onSuccess(data.proof);
|
||||
}
|
||||
}, 1500); // wait for animation to finish before sending the proof to mobile
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@mui/material": "^6.0.2",
|
||||
"@openpassport/core": "^0.0.9",
|
||||
"@openpassport/qrcode": "^0.0.12",
|
||||
"@openpassport/core": "^0.0.11",
|
||||
"@openpassport/qrcode": "^0.0.14",
|
||||
"axios": "^1.7.7",
|
||||
"next": "14.2.8",
|
||||
"react": "^18",
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
'use client';
|
||||
|
||||
import OpenPassportQRcode from '../../../../../qrcode/OpenPassportQRcode';
|
||||
import { OpenPassportQRcode } from '@openpassport/qrcode';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
|
||||
import { OpenPassportVerifier, OpenPassportDynamicAttestation } from '@openpassport/core';
|
||||
export default function Prove() {
|
||||
const userId = uuidv4();
|
||||
const scope = 'scope';
|
||||
|
||||
const openPassportVerifier: OpenPassportVerifier = new OpenPassportVerifier('prove_offchain', scope)
|
||||
.discloseNationality()
|
||||
.allowMockPassports();
|
||||
const openPassportVerifier: OpenPassportVerifier = new OpenPassportVerifier('prove_onchain', scope)
|
||||
.enableOFACCheck()
|
||||
.excludeCountries('Iran (Islamic Republic of)');
|
||||
|
||||
return (
|
||||
<div className="h-screen w-full bg-white flex flex-col items-center justify-center gap-4">
|
||||
<OpenPassportQRcode
|
||||
@@ -18,8 +21,6 @@ export default function Prove() {
|
||||
userIdType={'uuid'}
|
||||
openPassportVerifier={openPassportVerifier}
|
||||
onSuccess={(attestation) => {
|
||||
const dynamicAttestation = new OpenPassportDynamicAttestation(attestation);
|
||||
console.log('nationality:', dynamicAttestation.getNationality());
|
||||
// send the code to the backend server
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -8,10 +8,13 @@ import axios from 'axios';
|
||||
export default function Prove() {
|
||||
const userId = uuidv4();
|
||||
const scope = 'scope';
|
||||
const openPassportVerifier = new OpenPassportVerifier(
|
||||
'register',
|
||||
scope
|
||||
).setCommitmentMerkleTreeUrl(COMMITMENT_TREE_TRACKER_URL).allowMockPassports();
|
||||
|
||||
|
||||
const openPassportVerifier = new OpenPassportVerifier('register', scope)
|
||||
.setCommitmentMerkleTreeUrl(COMMITMENT_TREE_TRACKER_URL);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="h-screen w-full bg-white flex flex-col items-center justify-center gap-4">
|
||||
<OpenPassportQRcode
|
||||
|
||||
Reference in New Issue
Block a user