Merge pull request #250 from openpassport-org/dev

update registry
This commit is contained in:
turnoffthiscomputer
2024-12-01 19:26:56 +01:00
committed by GitHub
40 changed files with 2804 additions and 2378 deletions

View File

@@ -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"

View File

@@ -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",

View File

@@ -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');

View File

@@ -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),

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

1
registry/.yarnrc.yml Normal file
View File

@@ -0,0 +1 @@
nodeLinker: node-modules

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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"
}

View File

@@ -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");

View File

@@ -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");

View 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"

View File

@@ -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])
}

View 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
View 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();

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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,

View 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'
}

View 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' };
}
}

View 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();
}

View File

@@ -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');
}

View File

@@ -1,5 +0,0 @@
import * as fs from 'fs';
import * as path from 'path';
import { processCertificate } from './utils';

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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();
}

File diff suppressed because it is too large Load Diff

View File

@@ -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

Binary file not shown.

View File

@@ -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"
}
}
}

View File

@@ -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

View File

@@ -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",

View File

@@ -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
}}
/>

View File

@@ -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