fabric java sdk啓用tls

環境搭建

  適用Fabric版本:1.x及2.x
  如果尚未搭建一個可用的SDK測試網絡,可參考:
    Fabric SDK測試網絡搭建(v1.x)
    Fabric2.0 SDK測試網絡搭建

Peer和Orderer節點啓用TLS

  官方SDK地址:fabric-sdk-java
  廢話不說,直接上官方Java SDK代碼。

/**
* @methodsName: getEndPointProperties
* @description: 獲取Peer和Orderer的tls配置
* @param:  type(節點類型:peer或orderer)
* @param:  name爲節點域名
* @return: Properties 
*/
public Properties getEndPointProperties(final String type, final String name) {
        
        Properties ret = new Properties();
        final String domainName = getDomainName(name);//獲取Peer和Orderer節點域名後綴
        File cert = Paths.get(getTestChannelPath(), "crypto-config/ordererOrganizations".replace("orderer", type), domainName, type + "s",
                name, "tls/server.crt").toFile(); //getTestChannelPath()爲證書文件夾crypto-config所在目錄,自行替換
        if (!cert.exists()) {
            throw new RuntimeException(String.format("Missing cert file for: %s. Could not find at location: %s", name,
                    cert.getAbsolutePath()));
        }
        //此處判斷是否運行版本爲1.0及以後,鑑於目前運用較多爲1.x版本,此判斷邏輯可去除
        if (!isRunningAgainstFabric10()) {
            File clientCert;
            File clientKey;
            if ("orderer".equals(type)) {
                clientCert = Paths.get(getTestChannelPath(), "crypto-config/ordererOrganizations/example.com/users/[email protected]/tls/client.crt").toFile();

                clientKey = Paths.get(getTestChannelPath(), "crypto-config/ordererOrganizations/example.com/users/[email protected]/tls/client.key").toFile();
            } else {
                clientCert = Paths.get(getTestChannelPath(), "crypto-config/peerOrganizations/", domainName, "users/User1@" + domainName, "tls/client.crt").toFile();
                clientKey = Paths.get(getTestChannelPath(), "crypto-config/peerOrganizations/", domainName, "users/User1@" + domainName, "tls/client.key").toFile();
            }

            if (!clientCert.exists()) {
                throw new RuntimeException(String.format("Missing  client cert file for: %s. Could not find at location: %s", name,
                        clientCert.getAbsolutePath()));
            }

            if (!clientKey.exists()) {
                throw new RuntimeException(String.format("Missing  client key file for: %s. Could not find at location: %s", name,
                        clientKey.getAbsolutePath()));
            }
            ret.setProperty("clientCertFile", clientCert.getAbsolutePath());
            ret.setProperty("clientKeyFile", clientKey.getAbsolutePath());
        }

        ret.setProperty("pemFile", cert.getAbsolutePath());

        ret.setProperty("hostnameOverride", name);
        ret.setProperty("sslProvider", "openSSL");
        ret.setProperty("negotiationType", "TLS");

        return ret;
    }

/**
* @methodsName: getDomainName
* @description: 獲取Peer和Orderer節點域名後綴(例如org1.example.com)
* @param:  name爲節點
* @return: String 
*/
 private String getDomainName(final String name) {
        int dot = name.indexOf(".");
        if (-1 == dot) {
            return null;
        } else {
            return name.substring(dot + 1);
        }

    }

  Peer節點調用方法:

	Properties peerProperties = testConfig.getEndPointProperties("peer", name);//testConfig參考上文
	if (peerProperties == null) {
    	 peerProperties = new Properties();
	}
	peerProperties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", 9000000);
	Peer peer = client.newPeer(peerName, peerLocation,peerProperties);//client爲HFClient對象

  Orderer節點調用方法:

	Properties ordererProperties = testConfig.getEndPointProperties("orderer", name);
	ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTime", new Object[] {5L, TimeUnit.MINUTES});
	ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTimeout", new Object[] {8L, TimeUnit.SECONDS});
	ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveWithoutCalls", new Object[] {true});
	Orderer orderer = client.newOrderer(orderName, sampleOrg.getOrdererLocation(orderName),
                    ordererProperties);

CA節點啓用TLS

  網上大多數博客都是關於Orderer和Peer啓用TLS的,對於CA啓用TLS的資料較少,作爲良心博主,直接上乾貨。

    File cf = new File(cert);
    if (!cf.exists() || !cf.isFile()) {
         throw new RuntimeException("TEST is missing cert file " + cf.getAbsolutePath());
    }
    Properties properties = new Properties();
    properties.setProperty("pemFile", cf.getAbsolutePath());
    properties.setProperty("allowAllHostNames", "true"); 
    CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
    //創建HFCAClient 實例,caUrl爲ca地址,啓用tls地址爲https開頭的,例如https://192.168.1.10:7054
    HFCAClient instance = HFCAClient.createNewInstance(caUrl, properties);
    instance.setCryptoSuite(cryptoSuite);

  需注意的一點是enroll時候,啓用tls寫法有所不同

	final EnrollmentRequest enrollmentRequestTLS = new EnrollmentRequest();
	enrollmentRequestTLS.addHost(caUrl);
	enrollmentRequestTLS.setProfile("tls");
	enrollment = instance.enroll(userName, secret,enrollmentRequestTLS);

  附官方源碼(不啓用tls)

  /**
     * Enroll the user with member service
     *
     * @param user   Identity name to enroll
     * @param secret Secret returned via registration
     * @return enrollment
     * @throws EnrollmentException
     * @throws InvalidArgumentException
     */
    public Enrollment enroll(String user, String secret) throws EnrollmentException, InvalidArgumentException {
        return enroll(user, secret, new EnrollmentRequest());
    }

  附官方源碼(啓用tls)


    /**
     * Enroll the user with member service
     *
     * @param user   Identity name to enroll
     * @param secret Secret returned via registration
     * @param req    Enrollment request with the following fields: hosts, profile, csr, label, keypair
     * @return enrollment
     * @throws EnrollmentException
     * @throws InvalidArgumentException
     */

    public Enrollment enroll(String user, String secret, EnrollmentRequest req) throws EnrollmentException, InvalidArgumentException {

        logger.debug(format("url:%s enroll user: %s", url, user));

        if (Utils.isNullOrEmpty(user)) {
            throw new InvalidArgumentException("enrollment user is not set");
        }
        if (Utils.isNullOrEmpty(secret)) {
            throw new InvalidArgumentException("enrollment secret is not set");
        }

        if (cryptoSuite == null) {
            throw new InvalidArgumentException("Crypto primitives not set.");
        }

        setUpSSL();

        try {
            String pem = req.getCsr();
            KeyPair keypair = req.getKeyPair();
            if (null != pem && keypair == null) {
                throw new InvalidArgumentException("If certificate signing request is supplied the key pair needs to be supplied too.");
            }
            if (keypair == null) {
                logger.debug("[HFCAClient.enroll] Generating keys...");

                // generate ECDSA keys: signing and encryption keys
                keypair = cryptoSuite.keyGen();

                logger.debug("[HFCAClient.enroll] Generating keys...done!");
            }

            if (pem == null) {
                String csr = cryptoSuite.generateCertificationRequest(user, keypair);
                req.setCSR(csr);
            }

            if (caName != null && !caName.isEmpty()) {
                req.setCAName(caName);
            }
            String body = req.toJson();

            String responseBody = httpPost(getURL(HFCA_ENROLL), body,
                    new UsernamePasswordCredentials(user, secret));

            logger.debug("response:" + responseBody);

            JsonReader reader = Json.createReader(new StringReader(responseBody));
            JsonObject jsonst = (JsonObject) reader.read();

            boolean success = jsonst.getBoolean("success");
            logger.debug(format("[HFCAClient] enroll success:[%s]", success));

            if (!success) {
                throw new EnrollmentException(format("FabricCA failed enrollment for user %s response success is false.", user));
            }

            JsonObject result = jsonst.getJsonObject("result");
            if (result == null) {
                throw new EnrollmentException(format("FabricCA failed enrollment for user %s - response did not contain a result", user));
            }

            Base64.Decoder b64dec = Base64.getDecoder();

            String signedPem = new String(b64dec.decode(result.getString("Cert").getBytes(UTF_8)));
            logger.debug(format("[HFCAClient] enroll returned pem:[%s]", signedPem));

            JsonArray messages = jsonst.getJsonArray("messages");
            if (messages != null && !messages.isEmpty()) {
                JsonObject jo = messages.getJsonObject(0);
                String message = format("Enroll request response message [code %d]: %s", jo.getInt("code"), jo.getString("message"));
                logger.info(message);
            }
            logger.debug("Enrollment done.");

            return new X509Enrollment(keypair, signedPem);

        } catch (EnrollmentException ee) {
            logger.error(format("url:%s, user:%s  error:%s", url, user, ee.getMessage()), ee);
            throw ee;

        } catch (Exception e) {
            EnrollmentException ee = new EnrollmentException(format("Url:%s, Failed to enroll user %s ", url, user), e);
            logger.error(e.getMessage(), e);
            throw ee;
        }

    }

總結

  本篇博客完成了啓用TLS(Peer,Orderer,CA)時,Java SDK的寫法,有疑問歡迎評論留言。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章