/** * Copyright 2014-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package node.mgr.test.cert; import java.io.*; import java.security.*; import java.security.cert.*; import java.util.*; import com.webank.webase.node.mgr.base.tools.NodeMgrTools; import org.fisco.bcos.web3j.crypto.ECKeyPair; import org.fisco.bcos.web3j.crypto.Keys; import org.fisco.bcos.web3j.utils.Numeric; import org.junit.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.util.Assert; import sun.security.ec.ECPublicKeyImpl; import static com.webank.webase.node.mgr.base.tools.CertTools.byteToHex; /** * test load non-guomi cert and guomi cert * using java.security.cert.CertificateFactory getInstance("X.509"); * 2019/12 * replace java.security.cert.CertificateFactory * with org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory */ public class ImportCertTest { private final static String head = "-----BEGIN CERTIFICATE-----\n" ; private final static String tail = "-----END CERTIFICATE-----\n" ; @Test public void testPubAddress() throws IOException, CertificateException, IllegalAccessException, InstantiationException { /** * @param: nodeCert * 只有节点证书才是ECC椭圆曲线,获取pub的方法和区块链的一致 * 其余的agency chain 的crt都是rsa方法,使用大素数方法计算,不一样 */ // need crt file InputStream node = new ClassPathResource("node.crt").getInputStream(); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate nodeCert = (X509Certificate) cf.generateCertificate(node); // rsa算法的公钥和ecc的不一样 ECPublicKeyImpl pub = (ECPublicKeyImpl) nodeCert.getPublicKey(); byte[] pubBytes = pub.getEncodedPublicValue(); String publicKey = Numeric.toHexStringNoPrefix(pubBytes); String address = Keys.getAddress(publicKey); byte[] addByteArray = Keys.getAddress(pubBytes); System.out.println("byte[] : pub "); System.out.println(pubBytes); System.out.println("===================================="); System.out.println(publicKey); // 04e5e7efc9e8d5bed699313d5a0cd5b024b3c11811d50473b987b9429c2f6379742c88249a7a8ea64ab0e6f2b69fb8bb280454f28471e38621bea8f38be45bc42d System.out.println("byte[] to pub to address "); System.out.println(address); // f7b2c352e9a872d37a427601c162671202416dbc System.out.println("包含开头的04"); System.out.println(byteToHex(addByteArray)); } /** * address到底需不需要传入pub的开头的两位04 * 答案: 不需要,公钥是128位的 */ @Test public void testAddress() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException { ECKeyPair key = Keys.createEcKeyPair(); // 用byte[]穿进去获取公钥,就会可能多出一位0 byte[] pubBytes = key.getPublicKey().toByteArray(); System.out.println("=============原生的=============="); System.out.println(key.getPublicKey()); //64bytes BigInteger System.out.println(Keys.getAddress(key.getPublicKey())); System.out.println("===========通过转成hex后获取地址============"); System.out.println(Numeric.toHexStringNoPrefix(key.getPublicKey())); //Hex后显示 System.out.println(Keys.getAddress(Numeric.toHexStringNoPrefix(key.getPublicKey()))); System.out.println("===========通过byte[]============"); System.out.println(Numeric.toHexStringNoPrefix(pubBytes)); // BigInteget=> byte[] => hex 多一位 System.out.println(Keys.getAddress(Numeric.toHexStringNoPrefix(pubBytes))); System.out.println("==============="); // System.out.println(Keys.getAddress(pubBytes)); } @Test public void testImport() throws IOException, CertificateException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, NoSuchProviderException { // read from file is InputStream pem = new ClassPathResource("node.crt").getInputStream(); CertificateFactory cf = CertificateFactory.getInstance("X.509"); // agency's crt List<X509Certificate> certs = (List<X509Certificate>) cf.generateCertificates(pem); for(X509Certificate c: certs) { System.out.println(c.getSubjectDN()); } X509Certificate nodeCert = certs.get(0); // X509Certificate agencyCert = certs.get(1); // X509Certificate caCert = certs.get(2); // //只能验证上一级 // agencyCert.verify(caCert.getPublicKey()); // nodeCert.verify(agencyCert.getPublicKey()); /** * 根据subjectDN 获取证书类型,证书名字 */ } @Test public void getSingleCrtContent() throws IOException { // read from file is InputStream pem = new ClassPathResource("node.crt").getInputStream(); String certContent = getString(pem); List<String> list = new ArrayList<>(); String[] nodeCrtStrArray = certContent.split(head); for(int i = 0; i < nodeCrtStrArray.length; i++) { String[] nodeCrtStrArray2 = nodeCrtStrArray[i].split(tail); for(int j = 0; j < nodeCrtStrArray2.length; j++) { String ca = nodeCrtStrArray2[j]; if(ca.length() != 0) { list.add(formatStr(ca)); } } } for(String s: list) { System.out.println(s); System.out.println(); } } public static String formatStr(String string) { return string.substring(0, string.length() - 1); } public static String getString(InputStream inputStream) throws IOException { byte[] bytes = new byte[0]; bytes = new byte[inputStream.available()]; inputStream.read(bytes); String str = new String(bytes); return str; } public String getFingerPrint(X509Certificate cert)throws Exception { // 指纹 /** * Microsoft's presentation of certificates is a bit misleading * because it presents the fingerprint as if it was contained in the certificate * but actually Microsoft has to calculate the fingerprint, too. * This is especially misleading because a certificate actually has many fingerprints, * and Microsoft only displays the fingerprint it seems to use internally, i.e. the SHA-1 fingerprint. */ String finger = NodeMgrTools.getCertFingerPrint(cert.getEncoded()); System.out.println("指纹"); System.out.println(finger); return finger; } public static boolean isExpired2(X509Certificate cert) { try { cert.checkValidity(); return false; } catch (CertificateExpiredException e) { System.out.println("Certificate Expired"); return true; } catch (CertificateNotYetValidException e) { System.out.println("Certificate Not Yet Valid"); return true; } catch (Exception e) { System.out.println("Error checking Certificate Validity. See admin."); return true; } } /** * import guomi node cert list * @throws CertificateEncodingException */ @Test public void testLoadCertList() throws CertificateException, IOException { // need gmnode.crt file InputStream nodes = new ClassPathResource("sdk_node.crt").getInputStream(); org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory factory = new org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory(); List<X509Certificate> certs = (List<X509Certificate>) factory.engineGenerateCertificates(nodes); Assert.notNull(certs,"certs null"); certs.stream().forEach(c -> { System.out.println(c.getSubjectDN()); try { System.out.println(NodeMgrTools.getCertFingerPrint(c.getEncoded())); } catch (CertificateEncodingException e) { e.printStackTrace(); } }); } }