Messages between Provider and Aggregator and Aggregator and Operator, need to be signed on the sender and verified on the receiver。
The API_KEY and API_KEY_SECRET will be generated when Operator or Provider is added into Aggregator.
API_KEY and API_KEY_SECRET
For API_KEY, we can remove the hyphens from a UUID as the value.
For API_KEY_SECRET, we can generate a random Base64 string as the value with the Golang code below.
funcgenerateAPIKeySecret(lengthint)(string,error){iflength<=0{return"",fmt.Errorf("length must be positive")}// Calculate the number of random bytes needed.// Base64 encoding expands the data by 4/3, so we need to generate less bytes// to get the desired length after encoding. We round up to ensure we get at least the desired length.b:=make([]byte,(length*3+3)/4)_,err:=rand.Read(b)iferr!=nil{return"",fmt.Errorf("error generating random bytes: %w",err)}returnbase64.StdEncoding.EncodeToString(b),nil}
Signing and Verification
Before signing the message, we need to generate the canonicalized message from the request.
For GET request, the canonicalized message will be the key=value pairs concatenated with & as below.
For other request like POST, the canonicalized message will be the request body.
HMAC-SHA256 will be used for signing the message to get the signature.
After message is signed on the sender side, we will include API_KEY and signature generated above in two extra headers as below in the http request.
On the receiver side, API_KEY in X-API-KEY header will be used to retrieve the API_KEY_SECRET from the database and sign the message to get the signature and compare with X-SIGNATURE header value. If they are identical, the message can be further processed by Aggregator, otherwise dropped and return http status code 403 with Unauthenticated error to the sender.