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的写法,有疑问欢迎评论留言。
在这里插入图片描述

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