CertPathBuilder验证证书
总结 + plugin-power作用
- 主要是验证证书,在输入激活码时,会用idea自签名证书JetProfile CA的公钥验证激活码中的证书(但是这个好像无关紧要,无论成功还是失败激活码验证结果都一样)
- 比如keys-XIZQAN09CR-idea.key,在sun.security.rsa.RSASignature.engineVerify解密的bytes根本不像是PKCS1Padding数据,所以验证必定失败
- plugin-power是匹配x、y、z即m(cipherSignature)、e(CAPublicKey)、n(CAPublicKey),返回一个result(其实就是
MessageDigest.getInstance("SHA256").digest(ideaKeyCert.getTBSCertificate())
验证代码
private static void verifyRuleArgs()
throws CertificateException, FileNotFoundException, RuntimeException {
String powerConfigResult1 = "EQUAL,108391492724719606277191711676038310454333436786970899072879934267610324870870961974305689698304529291751931883693569275416671653649715395540162187908455880751887548211257780817773830153477469379663893839249632010489688404104740814832791608983255964373246023808678041003248593298915323068020141515280275870731964298697511434302901212533563571472947179437111243030002421474283363073021442715554541318313064598900684758246291687123240210640543678544269324094608551763049140564128299834843381841274260516105408318037686490277144538983963856617365418526798235932271319705894170543971766101775628884107261100637290512593943587295268337137890353216997114446658051251047509442298463526766678103653729776506979657957966027949436493606289520405331110453990512846697802196701678785414928082416405650857741201229183421400567636999723106788808933737428330992184832395299929033666381663232693108552887968738513151493044369308652310586803160326722967115451573652070286501044484503083240302303438554529551204609089966636092666792347623413483134664670641246129954999815529917163967761617333572567787618346281658716181608204191963817312534492517480248086896060880038259592723773361709406277837609546030729611710076711450268767610513506889086815865283,65537,860106576952879101192782278876319243486072481962999610484027161162448933268423045647258145695082284265933019120714643752088997312766689988016808929265129401027490891810902278465065056686129972085119605237470899952751915070244375173428976413406363879128531449407795115913715863867259163957682164040613505040314747660800424242248055421184038777878268502955477482203711835548014501087778959157112423823275878824729132393281517778742463067583320091009916141454657614089600126948087954465055321987012989937065785013284988096504657892738536613208311013047138019418152103262155848541574327484510025594166239784429845180875774012229784878903603491426732347994359380330103328705981064044872334790365894924494923595382470094461546336020961505275530597716457288511366082299255537762891238136381924520749228412559219346777184174219999640906007205260040707839706131662149325151230558316068068139406816080119906833578907759960298749494098180107991752250725928647349597506532778539709852254478061194098069801549845163358315116260915270480057699929968468068015735162890213859113563672040630687357054902747438421559817252127187138838514773245413540030800888215961904267348727206110582505606182944023582459006406137831940959195566364811905585377246353->31872219281407242025505148642475109331663948030010491344733687844358944945421064967310388547820970408352359213697487269225694990179009814674781374751323403257628081559561462351695605167675284372388551941279783515209238245831229026662363729380633136520288327292047232179909791526492877475417113579821717193807584807644097527647305469671333646868883650312280989663788656507661713409911267085806708237966730821529702498972114194166091819277582149433578383639532136271637219758962252614390071122773223025154710411681628917523557526099053858210363406122853294409830276270946292893988830514538950951686480580886602618927728470029090747400687617046511462665469446846624685614084264191213318074804549715573780408305977947238915527798680393538207482620648181504876534152430149355791756374642327623133843473947861771150672096834149014464956451480803326284417202116346454345929350148770746553056995922154382822307758515805142704373984019252210715650875853634697920708113806880196144197384637328982263167395073688501517286678083973976140696077590122053014085412828620051470085033364773099146103525313018873319293728800442101520384088109603555959893639842091339193857485407672132882577840295039058621747654642202620767068924079813640067442975";
String[] ruleSplit = powerConfigResult1.split("->");
String[] argsSplit1 = ruleSplit[0].split(",");
String x = argsSplit1[1];
String y = argsSplit1[2];
String z = argsSplit1[3];
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
String certPath = "C:/Users/LYM/code/break_scripts/license-XIZQAN09CR.crt";
String caCertPath = "C:/Users/LYM/code/break_scripts/idea-rootca.crt";
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(
new FileInputStream(certPath));
X509Certificate caCert = (X509Certificate) certificateFactory.generateCertificate(
new FileInputStream(caCertPath));
String mm = new BigInteger(1, cert.getSignature()).toString();
RSAPublicKey caPublicKey = (RSAPublicKey) caCert.getPublicKey();
String caPublicKeyN = caPublicKey.getModulus().toString();
String caPublicKeyE = caPublicKey.getPublicExponent().toString();
boolean sigEqualDecryptSig = false;
try {
Method toByteArrayMethod = RSACore.class.getDeclaredMethod("toByteArray", BigInteger.class,
int.class);
toByteArrayMethod.setAccessible(true);
byte[] replacedDecrypted = (byte[]) toByteArrayMethod.invoke(null,
new BigInteger(ruleSplit[1].trim()),
RSACore.getByteLength(caPublicKey.getModulus()));
RSAPadding padding = RSAPadding.getInstance(RSAPadding.PAD_BLOCKTYPE_1,
RSACore.getByteLength(caPublicKey));
sigEqualDecryptSig = MessageDigest.isEqual(
MessageDigest.getInstance("SHA256").digest(cert.getTBSCertificate()),
RSASignature.decodeSignature(ObjectIdentifier.of("2.16.840.1.101.3.4.2.1"),
padding.unpad(replacedDecrypted)));
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.printf(
"equal x is m? %s, y is e? %s, z is n? %s, sigEqualDecryptSig ? %s\nm=%s\ncaPublicKeyN=%s\ncaPublicKeyE=%s\n",
x.equals(mm), y.equals(caPublicKeyE), z.equals(caPublicKeyN), sigEqualDecryptSig,
mm, caPublicKeyN, caPublicKeyE
);
}
idea-rootca.crt
MIIFOzCCAyOgAwIBAgIJANJssYOyg3nhMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0EwHhcNMTUxMDAyMTEwMDU2WhcNNDUxMDI0MTEwMDU2WjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0tQuEA8784NabB1+T2XBhpB+2P1qjewHiSajAV8dfIeWJOYGy+ShXiuedj8rL8VCdU+yH7Ux/6IvTcT3nwM/E/3rjJIgLnbZNerFm15Eez+XpWBlm5fDBJhEGhPc89Y31GpTzW0vCLmhJ44XwvYPntWxYISUrqeR3zoUQrCEp1C6mXNXEpqIGIVbJ6JVa/YI+pwbfuP51o0ZtF2rzvgfPzKtkpYQ7m7KgA8g8ktRXyNrz8boiwg7RRPeqs4uL/RK8d2KLpgLqcAB9WDpcEQzPWegbDrFO1F3z4UVNH6hrMfOLGVAxoiQhNFhZj6RumBXlPS0rmCOCkUkWrDr3l6Z3spUVgoeea+QdX682j6t7JnakaOwjzwY777SrZoi9mFFpLVhfb4haq4IWyKSHR3/0BlWXgcgI6w6LXm+V+ZgLVDON52FLcxnfftaBJz2yclEwBohq38rYEpb+28+JBvHJYqcZRaldHYLjjmb8XXvf2MyFeXrSopYkdzCvzmiEJAewrEbPUaTllogUQmnv7Rv9sZ9jfdJ/cEn8e7GSGjHIbnjV2ZMQ9vTpWjvsT/cqatbxzdBo/iEg5i9yohOC9aBfpIHPXFw+fEj7VLvktxZY6qThYXRRus1WErPgxDzVpNp+4gXovAYOxsZak5oTV74ynv1aQ93HSndGkKUE/qA/JECAwEAAaOBhzCBhDAdBgNVHQ4EFgQUo562SGdCEjZBvW3gubSgUouX8bMwSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAjrPAZ4xC7sNiSSqh69s3KJD3Ti4etaxcrSnD7r9rJYpKBMviCKZRKFbLv+iaF5JK5QWuWdlgA37ol7mLeoF7aIA9b60Ag2OpgRICRG79QY7ouLviF/yRMqm6yno7NYkGLd61e5Huu+BfT459MWG9RVkG/DY0sGfkyTHJS5xrjBV6hjLG0lf3orwqOlqSNRmhvn9sMzwAP3ILLM5VJC5jNF1zAk0jrqKz64vuA8PLJZlLS9TZJIYwdesCGfnN2AETvzf3qxLcGTF038zKOHUMnjZuFW1ba/12fDK5GJ4i5y+nfDWVZVUDYOPUixEZ1cwzmf9Tx3hR8tRjMWQmHixcNC8XEkVfztID5XeHtDeQ+uPkX+jTDXbRb+77BP6n41briXhm57AwUI3TqqJFvoiFyx5JvVWG3ZqlVaeU/U9e0gxn8qyR+ZA3BGbtUSDDs8LDnE67URzK+L+q0F2BC758lSPNB2qsJeQ63bYyzf0du3wB/gb2+xJijAvscU3KgNpkxfGklvJD/oDUIqZQAnNcHe7QEf8iG2WqaMJIyXZlW3me0rn+cgvxHPt6N4EBh5GgNZR4l0eaFEV+fxVsydOQYo1RIyFMXtafFBqQl6DDxujlFeU3FZ+Bcp12t7dlM4E0/sS1XdL47CfGVj4Bp+/VbF862HmkAbd7shs7sDQkHbU=
keys-XIZQAN09CR-idea.key
XIZQAN09CR-eyJsaWNlbnNlSWQiOiJYSVpRQU4wOUNSIiwibGljZW5zZWVOYW1lIjoia2lkZHkgaW5zZWFtcyIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IlBEQiIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNJIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUEMiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBDV01QIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUkIiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBQUyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiSUkiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQR08iLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBTVyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6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
-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
CertPathBuilder验证证书
- CertPathBuilder.param
- targetConstraints(CertSelector),即匹配Cert
- 匹配方法:SerialNumber,NotBefore、NotAfter、issuer、subject、时间合法等等,基本一致就行
- trustAnchors:信任证书,做CA的
- certStores:验证完的Cert
- CertPathBuilder#build会build2次,searchAllCertStores=false和true的
- 因为pathCompleted=false,则会返回null,而null就会再执行searchAllCertStores=true
- depthFirstSearchForward:
- 主要参数
- currState:携带userCert和issuerDN
- 一开始都为null,isInitial=true(即刚开始,userCert肯定是做不了CA的)
- dN:param.targetSubject,作为CA,该参数无用
- cpList:已验证或者不需要验证(即userCert)的CACerts
- param.targetSubject
- 优先
param.targetConstraints(CertSelector)
- 其次才是用param.targetConstraints在param.certStores选择一个
- 找CACerts:
- 如果currState.isInitial,则
ForwardBuilder\#getMatchingEECerts
- 优先certSelector.Certificate
- 其次params.certStore中的一个非自签名证书
- 否则
ForwardBuilder\#getMatchingCACerts
- 使用certSelector(currState.issuerDN)在ForwardBuilder.trustCerts(param.trustAnchors)找
- 根据trustedSubjectDNs(即信任证书的使用者)排序
- 一般只找一个,上面用的CertSelector,如果currState.isInitial,则是克隆param.targetConstraints,否则创建一个
- 遍历CACerts
- CACert校验currState.userCert
ForwardBuilder\#verifyCert(caCert, currState, caCerts)
- CACert不能在certList(不能重复使用)
- CACert不在trustedCerts(param.trustAnchors),则需要检查一下(好像没什么,甚至不需要检查)
!currState.isInitial时,currState.cert.verify(cert.getPublicKey(), buildParams.sigProvider())
- 即第一个不验证(userCert不验证userCert)
- 即
userCert.verify(caCert.public)
- buildParams.sigProvider()一般是null
!ForwardBuilder\#isPathCompleted(caCert)
- certList.add(CACert)
- 调用state.updateState
- currState.userCert=CACert
- currState.issuerDN=CACert.IssuerX500Principal
- CACert.IssuerX500Principal作为dN,递归调用自己(depthFirstSearchForward)
ForwardBuilder\#isPathCompleted(CACert)==true条件
- CACert在params.trustAnchors中
- 或者trustAnchor无trustedCert时
- CACert的SubjectX500Principal(CA信息如CN等)、PublicKey与trustAnchor的CA和PublicKey相同
- 且不是DSAPublicKey或者如果是则DSAPublicKey无param
- 且
caCert.verify(trustAnchor.publicKey, this.buildParams.sigProvider())
- 此时caCert是userCert,而传入的无cert的trustAnchor才是CACert
- 如果完成了,则设置this.trustAnchor=这个trustAnchor
- 简单来说就是:CAcCert必须是信任的CA才结束,如果还是不信任,就继续那当前CACert的CA验证
- 开始时传入了有CACert的trustAnchor
- 或者有CACert的CA信息+PublicKey的trustAnchor且CACert.verify(publicKey)=true(让CA的CA验证CA)
ForwardBuilder\#isPathCompleted(CACert):最后
- 构建CertPath:用appendedCerts(根据cpList,如果最后一个Cert被信任,就不加入)
- 构建Checkers:
- PolicyChecker
- AlgorithmChecker
- 如果keyParamsNeededFlag,即CACert是DSAPublicKeyWithoutParams,则加入BasicChecker
- 先用params.CertPathCheckers检查一下有没有RevocationChecker,没有且params.revocationEnabled=true(默认true)则加入
new RevocationChecker(builder.trustAnchor, this.buildParams)(使用params的CertStore和Certificates(to CertStore),以及最后一个CA的Publickey)
- 检查证书是否是撤销的,使用CRL
- 用CRLSelector从CertStores中根据当前Cert获取CRL对象,根据RevocationChecker.crlDP获取CRL
- 如果CRLs是空的,则verifyWithSeparateSigningKey
- 构建一个CertPathBuilder:根据当前的params构建一个新params
- trustAnchors(最后一个CA的anchor或者params.trustAnchors), targetConstraints(最后一个CA的PublicKey+CA信息即Subject,注意不是CACert)
- 再把params.CertPathCheckers也加入
- 遍历appendedCerts使用Checkers
- 遍历完,设置pathCompleted=true
- 最后,返回Result,trustAnchor是CA,CertPath是CA颁发的证书