Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular-crypto-service #34

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
305 changes: 305 additions & 0 deletions text/0000-modular-crypto-service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
---
layout: default
title: RFC Template
nav_order: 3
---

- Feature Name: modular_crypto_service
- Start Date: 2020-09-19
- RFC PR: (leave this empty)
- Fabric Component: core, fabric-sdk-*, fabric-ca
- Fabric Issue: (leave this empty)

# Summary
[summary]: #summary

One paragraph explanation of the feature.

This RFC aims to provide broader crypto service configurability or pluggable capability.
It mainly changes design of crypt/X509 usage and hash algorithm opt-in in several layer.

# Motivation
[motivation]: #motivation

Why are we doing this? What use cases does it support? What is the expected
outcome?

Following is the original initiative post, translated from Chinese.
```
The Hyperledger Fabric code project has a very wide range of adoptions in many domestic industries and institutions, and has a very basic role in the application of the blockchain industry.
According to Chinese policy requirements, it is necessary to support the national secret (GM) encryption algorithm. Many domestic enterprises and Fabric enthusiasts have successively carried out some corresponding national secret (GM) fabric forks with outstanding achievements. However, in this matter, there is serious duplication of working hours and waste of human resources.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain, or give a formal (English) reference to the bespoken policy? Is this policy only for intra-national networks? I'm asking because most of the world uses the (American) NIST standard - America, Australia, Europe, Africa and Asia.

When a person from China connects to a non chinese website, with overwhelming probability, that website uses the NIST approved algorithms. So, does this policy actually take place? How does the browser of the end user know which protocol to use when connecting to a site?

Copy link
Author

@davidkhala davidkhala Sep 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We stored a copy of one of original specifications in Financial distributed ledger technology security specification
More recently, there is another related specifications in Financial application of blockchain technology -- Evaluation rules

There might be a blur expression from our original initiative. Policy means some points like:
To promote GM crypto adoption in Critical Industries. This has been mentioned by government from about 10 years ago. 2020 we see the above specifications responding to this policy trend.

Formal English reference does not exist theoretically. But we TWGC are also working on an Fabric Evaluation on the first specs in Tencent doc. It is better formatted to apply google translate and maturity is Beta

About these specification applying scope, both above are limited to 'Finance', in level of 'Recommended'. So it will not apply to all intra-national network or internet. We can see it as an extension from FIPS series when coming to Financial DLT domain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two links you posted are in Chinese, I can't read them. Isn't there an English version somewhere?

About these specification applying scope, both above are limited to 'Finance', in level of 'Recommended'. So it will not apply to all intra-national network or internet. We can see it as an extension from FIPS series when coming to Financial DLT domain.

If it's recommended it means it's not mandatory, therefore since all businesses in China can still use the existing Fabric implementation, what business value does using Chinese crypto have?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required in practical use case. Increasing numbers of financial institution procument will add this specification as requirement to checklist. If it is indeed valueless, we would not have heard about questions and efforts to make a fabric-GM fork. Ignoring this is not prohibited but at least harmful.

Meanwhile I would like to highlight that this RFC does not aim to inject a native GM support in Fabric. We think for further.

@hartm Hart, what is your opinion?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a Fabric maintainer (or even contributor, just a free rider), so I don't think my opinion here will matter too much. But I do like the idea of a plugin crypto architecture for Fabric, which I think would be the cleanest way to do this (Fabric maintainers, please feel free to shoot me down if I'm way off), and I'm always happy to spout off an opinion, so I'll go ahead and comment.

There are other applications that a plugin architecture would enable. For instance, I'd like to be able to replace the core signing algorithms in Fabric with pairing-based signatures. We could then use threshold versions of these signature schemes for a number of useful blockchain applications. For instance, this would allow compact endorsements and small "proofs of blockchain state." I have a bunch more applications in mind that I'd be happy to talk about if people are curious that are too long for a comment here. These are obviously not related to government standards.

However, I think you probably want a much more detailed RFC than what is currently present (maybe I'm missing the details?). Can you propose the exact interfaces and functions you want for modular interoperability? I think the Fabric maintainers will potentially be much more receptive if you propose the kind of interface you want. It looks like just 1) a generic hash primitive and 2) a generic signature primitive will be enough. Figuring out what kinds of formats/functions will work best with Fabric will go a long way here.

Finally, doing something like this would be an ambitious project. The more you can do it in bite sized pieces, the better. It will make testing and security analysis much better. So it might be best if your plan was to come up with a generic interface, put your protocols in that interface, and then slowly migrate Fabric.

Anyways, I hope I'm not ruffling any feathers by commenting here. Thanks everyone for your hard work.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hartm Thanks for your valuable feedback. Indeed we are hard working to provide more details, and further changes to the RFC proposal will be pushed later.

Here, the Hyperledger Technical Working Group China (TWGC) proposes that the majority of Fabric enthusiasts and users gather and work together to create a standard national cryptographic project of Hyperledger Fabric, which is shared by everyone, and finally meet the needs of community maintainer request, merge into the Fabric up-stream.
```
We now have 3 streams of China crypto libraries under Hyperledger-TWGC github organization.
Some of them has also provided successful ane enterprise-proven bccsp implementations.
But as along as we go deeper into fabric source, we notice implementing bccsp only could not fulfill all of Chinese national crypto specification requirements.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BCCSP is not an abstraction worth saving and any work in this space should aim to replace it completely with something better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I do not dare to say so loudly. :- D. @guoger Jay has asked about this before. Yes, the design looks so Java than golang. But I personally have no idea how is a better practice in golang world.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For personal understanding here: even if the BCCSP looks like java than golang which still providing us with interface and we can design/change it following design patterns. We can implement particular design pattern via OO concept or else.

There are some crypto library usages outside of bccsp, such as communication protocol, X509 format conversion.
It relates to fabric architect design thus we need broader consensus and feedbacks from community as an RFC level change.

Additionally, the new design should take care of not only Chinese but for any other national crypto standards. So discussion below will focus on two parts.
- Adjust with new crypto standards to fabric in bccsp.
- Adjust with new crypto standards at community level.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

There are 3 configurations controlling hash algorithm used in fabric, separately.
- Fabric uses hash function in bccsp related to peer/orderer (controlling feature samples: signing)
- Fabric uses hash function based on `crypto_config` section in organization/msp level (controlling feature samples: private data)
- Fabric uses hash algorithm based on `HashingAlgorithm` value in channel level (controlling feature samples: block hash)

To apply new crypto standards at bccsp:
- As golang language, we have to rebuild the library as there no hot module adding or replacement way for golang.
- New crypto standards implemented following bccsp is needed. So we need to adjust parts of bccsp for ex
when a new X509 interface is introduced as much with national crypto standard or any new crypto standard. Rework of usage of `crypto/X509` includes making `crypto/X509` as an implementaion of new X509 interface.
- The changes for the new crypto standards should be less impacts for fabric and in a configurable way if possible.

This change should not impact Fabric usages if they are on default configuration. But it may impact on Fabric fork developers since we exposed more extensibility.

To fulfill national crypto standards, security of communication is a must.
Fabric family replies on classical https and gRPCs communication. So any implementation should firstly have another fork of crypto-complaint https/gRPCs.
After these forks become mature, incorporate them into individual national crypto fork of fabric.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I keep seeing a reference to a fork for all of the "special sauce." So, is the goal to make it easier to fork or to integrate with Fabric?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is our side goal. Make it easier and standardized for developer to have a crypto fabric fork in appropriate way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe an easy way too fork, but I suppose we should aim at integrate before we have to fork.

TWGC could provide a sample guideline of incorporation for Fabric forks, but not Fabric main-stream.

[**WIP**] feature examples, migration guideline

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

This is the technical portion of the RFC. Explain the design in sufficient
detail that:

- Its interaction with other features is clear.
- It is reasonably clear how the feature would be implemented.
- Corner cases are dissected by example.

The section should return to the examples given in the previous section, and
explain more fully how the detailed proposal makes those examples work.

[**WIP**] along with previous feature examples
## Detail proposal for BCCSP
```
- sw -> generalBSSCP
```
Overall speaking, we wanna to make BCCSP becomes a general workflow as blockchain crypto provider.
Which means, we are going to refactor current sw workflow with serval kind of design patterns.

Adapter pattern:
We can imaging that we have an abstract proto type of interface there invoked by bccsp interface(as key.go) and plays role as adapter with specific crypto library.(ECDSA, PKCS11, SM2, etc...)

Prototype pattern:
We can use ECDSA, and PKCS11 as prototype as default for software crypto and hardware crypto samples, which used in CI, release etc...

Factory pattern:
For example, to adapt with any new crypto library
- Someone need the crypto provider to implement the type(following prototype) and tested by themself.
- Once the adaptor been implemented, everyone hope it can be easily integrated with fabric.
1. <del>Someone fork fabric and code change etc... all doing by themself in specific forked branch.</del>
1. Someone fork fabric and copy pasted adaptor impl as part of bccsp package, then recomplie fabric. (so far sample shows this way)
1. Someone use fabric and compile adaptor, start fabric with adaptor binary as go plugin.

Command Pattern:
- Ref to above possbile ways of implemention, in either of solution, there need any paramter to decide with crypto library should be used.

Take publicKey To EncryptedPEM as sample:

#### Here is logic need to be added as a global wrapper to load plugin
currently, some part of logic is implemented here. https://github.com/Hyperledger-TWGC/fabric/tree/bccsp-gm
```go
// to do package gm
swbccsp.AddWrapper(reflect.TypeOf(&sm2.SM2PublicKey{}), &sm2.SM2PublicKeyKeyVerifier{})
......
func InitCryptoProviders() {
lock.Lock()
defer lock.Unlock()
// init
// publicKeyToEncryptedPEM
puk2epem = make(map[reflect.Type]func(k interface{}, pwd []byte) ([]byte, error))

//default AddWrapper for ecdsa
puk2epem[reflect.TypeOf(&ecdsa.PublicKey{})] = ECDSApublicKeyToEncryptedPEM

//AddWrapper for sm2
puk2epem[reflect.TypeOf(&ccssm2.PublicKey{})] = sm2.SM2publicKeyToEncryptedPEM
}
```
Full changes here: https://github.com/SamYuan1990/fabric/blob/packageRefactor/bccsp/sw/new.go#L107-L217

#### Here is the logic changed in current sw to fill with wrapper above.
```go
package sw

publicKeyToEncryptedPEM(k interface{}, pwd []byte){
for i,v := range GetfromWrapperMap() {
if k.type == i.type {
return do(k,v)
}
}
return "not supported"
}
```
Full changes here: https://github.com/SamYuan1990/fabric/blob/packageRefactor/bccsp/sw/keys.go#L315-L322

#### A sample function as specific crypto wrapper/provider
```go
package specific
import specific_crypto_lib

//example function
publicKeyToEncryptedPEM(k interface{}, pwd []byte){
specific impl
}
```
Full changes here: https://github.com/Hyperledger-TWGC/fabric/tree/bccsp-gm/bccsp/sm2

Option One:
With help for go plugin, we are able to do:
- Impl an interface as struct in plugin code.
- Load the type of the interface by reflect.
- Invoking interfaces method which provided by plugin.
- From raw type to create plugin struct.
For details, please refer https://github.com/SamYuan1990/go-plugindemo/blob/poc/main.go#L84-L110

```go
AddWapperMap(path string){
p, err := plugin.Open(path.so)
if err != nil {

panic(err)

}

initFunc, err := p.Lookup("init")
obj := initFunc().()

f, err := p.Lookup("publicKeyToEncryptedPEM")
...

my_type=reflect.Typeof(&obj)
//default for all type replacement
GlobalCryptoWrapper[my_type] = f
}
```

Then we can make different kind of plugin.so file with interface defined in BCCSP and make the crypto implmentation plugable by switching the file.

Option Two:
We don't use the go plugin, as the limitation for ex: https://github.com/golang/go/issues/31354
We put the specific crypto package as a part of bccsp package and rebuild fabric with the specific crypto package.(as build tag)
Full changes here: https://github.com/Hyperledger-TWGC/fabric/tree/bccsp-gm


### Refactor current bccsp with new process logic.
To make something as classloader in bccsp. There may need to build some global level map in `<type, function>` way. For example with below logic, we can reused `fileks.go` and by reflect, the code will auto switch between crypto logics which added.

### Implementing APIs basing on new crypto standards
Here are the list below for the APIs should be implemented.

## Detail proposal for sdk changes

On fabric sdk side, we need align with the changes, so that from client to network able to use same crypto alg/crypto cruve or tls cert...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personally prefer to see SDK support focused on the Fabric Gateway client API, which is implemented in Go, Node and Java. This API has been designed with a pluggable approach in mind. For example:

Note that the Fabric Gateway API is focused on business application runtime, including transaction invocation and eventing, not on operational concerns such as identity enrolment with a CA.

It would be good to understand whether the current Fabric Gateway API meets your needs and, if not, what additional requirements you have related to this RFC.

Copy link
Contributor

@SamYuan1990 SamYuan1990 Oct 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bestbeforetoday ,

Yes, we can ref to Gateway API to make changes for SDK side and refresh this part making them up to date, and there are some questions before we update description for this part in this RFC.

Only for java specific

  1. For my personal understanding, the grpcs changes is better/needed changed from grpc jar packages.
fabric-java-gateway/sdk
grpc.jar
connection level(netty?) we need change here to meet the request

so, at implementation level, we need to change at the connection level to match the "standard request".
sounds like we have two plan:

  • Plan A, just recompile netty and replace netty jar packages via mvn/gradle to have a try without updates fabric-java-gateway/grpc.jar if it is possible.
  • Plan B, making a customer impl for all the things and use application-provided gRPC connection

Also there maybe Plan C as with further considering that grpc matches TLS1.3 rfc and too see we can reuse TLS1.3 or not...
With reasons all above, you know that's the reason for now, just focusing on hash and sign logic in current documents.
But here I have a question about application-provided gRPC connection but where should user makes an object as io.grpc.Channel grpcChannel, compile fabric proto file and next?

  1. I am agree gateway sdk client is more easy for user for use, but considering for any existing application using sdk, before we announced as duplicates sdk by gateway. I suppose we need considering any existing application in rfc scope?

  2. if I am understand correctly, sign, hash, id(as cert import,export)... we are able to customer crypto related impls in java gateway sdk?

Considering other language

  1. it there any language such as golang/nodejs gateway supposes this kind of sample?

Overall speaking, I am glad to see if the gateway interface you are sharing resolved parts for the questions and I would like to ask @xiaohui249 's help here to double check if the interface you provide can help resolve hash, sign and id.

CC: @davidkhala

:-)
Sam

Copy link
Member

@bestbeforetoday bestbeforetoday Nov 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Java client API for Fabric Gateway just requires a gRPC Channel object to be passed in as the gRPC connection to use. This is a very simple abstract class so you could provide your own complete channel implementation that just extends that class if the gRPC ManagedChannel implementation cannot be made to work for you as required. The Fabric Gateway client API should not need any changes.

The Fabric Gateway client API just uses whatever hash and signing implementation you provide, so you can use whatever crypto implementation you want with no changes to the Fabric Gateway client API. At least provided that crypto implementation uses the pattern of hashing a message to create a digest, and then generating signature bytes from that digest. At the server end the usual Fabric mechanisms are used so Fabric Gateway doesn't make it any easier (or more difficult) to provide a server crypto implementation that matches the client implementation.

The Fabric Gateway client API has very similar implementations in Java, Node and Go, so it is just as easy to plug in your own crypto implementation in each language. The gRPC connection details are slightly different as the gRPC implementation in each language are slightly different.

The Go client requires a grpc.ClientConn, which is a struct so not easily replaceable with your own implementation. The Node client requires a gRPC Client object. If we really had to allow alternative gRPC implementations in these languages, we could probably implement some abstraction to make that possible -- in fact the unit tests already make use of similar internal abstractions -- but I suspect a better route might be to enhance the gRPC libraries themselves if they don't currently provide the required capability.

Of course you are free to target existing SDKs too but I would definitely like for the Fabric Gateway client API to be included. Based on my understanding of what you are trying to achieve, it sounds like the Fabric Gateway client API will be much easier to use the way you want than the existing SDKs.


### Detail Proposal for java sdk changes.
For java SDK, we need refactor `org.hyperledger.fabric.sdk.security` package.
1. supporting dynamic class loading with a modular crypto service jar package as implementation of `org.hyperledger.fabric.sdk.security`.
1. the implation should implate for both msp/identity load from cert file.
1. the implation should implate for tls connection.

#### detail changes for `org.hyperledger.fabric.sdk.security`
step 1: As `org.hyperledger.fabric.sdk.security.certgen` also a factory pattern on design which builder class to create keypair class for tls. we are able to refactor those two class into a factory interface and a impl interface.
step 2: as all classes in `org.hyperledger.fabric.sdk.security` in factory pattern, a refactor can be made to make this package following factory pattern.
step 3: the factory of `org.hyperledger.fabric.sdk.security` should support dynamic class load from an external jar file if provided. or use current implementation by default.

#### if someone is going to implate a modular crypto service for java sdk
step 1: for msp loading, impls interface defined in https://github.com/hyperledger/fabric-sdk-java/blob/master/src/main/java/org/hyperledger/fabric/sdk/security/CryptoSuite.java
step 2: for tls config, impls new interface defined in step 1 above as refactor result for package `org.hyperledger.fabric.sdk.security.certgen`
step 3: for class loader, impls factory class defined as steps 3 above as refacotr result for package `org.hyperledger.fabric.sdk.security`

#### Drawbacks & A sample solution/workaround
For java sdk, there some low level code outside fabric java sdk scope but as dependencies, for ex `io.netty`.
A general solution for this is treating those jar dependencies as interfaces.
Modular crypto sevice provider should impl a changes for those jar dependencies by themselves.

# Drawbacks
[drawbacks]: #drawbacks

Why should we *not* do this? Are there any risks that must be considered along with
this rfc.

**AS IS**. No matter how we improve fabric pluggable flexibility, developer still have to maintain a Fabric fork with all plugin equipped.
Does this RFC really help a lot when comparing fashions:
1. let developer change every hardcode cryptoSuite into another national crypto hardcode cryptoSuite.
1. let developer implement a plugin under the restriction of interface, and carefully port into fabric source.

**Fabric Family interopt**
For Fabric surrounding projects such as SDKs and other hyperledger projects with Fabric support, for a specific nation crypto standard Fabric fork.
developer community still have to make another SDK fork in order to satisfy secured communication. A lot of cross validation is there.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, to me, complicates the ecosystem quite a bit. This really does imply that once Fabric is forked for crypto, each of the SDKs get a fork, the documentation gets a fork, the build processes fork, CI gets a fork, the maintenance process forks, etc.

So, while I support making Fabric more malleable, it's a small piece of the overall solution space.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sykesm we have similar concern and discussion of this complexity. Is there any better and smart roadmap per you think that we can switch to?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this part, if we just make the bccsp package modular, which means we may don't need to impacts with CI and others. For SDK we will need it supports with a new module for crypto alg implementation...


**System incompatible**
For a running fabric network (mainstream) using current default configuration value, according to our design, there is no upgrade operation needed.
But some corner cases and risks are:
- if channel config `HashingAlgorithm` is changed to an unrecognizable value, there will be unpredictable behavior
- if channel config `HashingAlgorithm` is changed in the middle, there will be unpredictable behavior


# Rationale and alternatives
[alternatives]: #alternatives

- Why is this design the best in the space of possible designs?
- What other designs have been considered and what is the rationale for not
choosing them?
- What is the impact of not doing this?

same as Motivation section

# Prior art
[prior-art]: #prior-art

Discuss prior art, both the good and the bad, in relation to this proposal.
A few examples of what this can include are:

- For consensus, global state, transaction processors, and smart contracts
implementation proposals: Does this feature exists in other distributed
ledgers and what experience have their communities had?
- For community proposals: Is this done by some other community and what were
their experiences with it?
- For other teams: What lessons can we learn from what other communities have
done here?
- Papers: Are there any published papers or great posts that discuss this? If
you have some relevant papers to refer to, this can serve as a more detailed
theoretical background.

This section is intended to encourage you as an author to think about the
lessons from other distributed ledgers, provide readers of your RFC with
a fuller picture. If there is no prior art, that is fine - your ideas are
interesting to us whether they are brand new or if it is an adaptation.

Note that while precedent set by other distributed ledgers is some motivation,
it does not on its own motivate an RFC. Please also take into consideration
that Fabric sometimes intentionally diverges from common distributed
ledger/blockchain features.

[**WIP**] We take several references from FISCO/BCOS for multiple language implementation of Chinese national standard.
We also take reference from famous Crypto library BouncyCastle which has almost native support for Chinese national EC.
BouncyCastle also provide a reference in X509 interface design.


# Testing
[testing]: #testing

- Test plan automates importing this implementation to fabric and run regression fabric test



# Dependencies
[dependencies]: #dependencies

https://jira.hyperledger.org/browse/FAB-5496


# Unresolved questions
[unresolved]: #unresolved-questions

Current clumsy but fast solution is that we copy a bccsp into fabric source and rebuild.
If fabric community can agree on a framework supporting dependency-inject in golang (aside from go plugin), it could be smarter.