when I tried to enroll the "admin" user, the second call to CreateCertificatePair failed with the "Signature verification failed" message. BTW, I copied the enrollUser function from the eca_test.go. And those tests under membersrvc/ca package can be passed.
//Phase 2 of the protocol
spi := ecies.NewSPI()
eciesKey, err := spi.NewPrivateKey(nil, encPriv)
if err != nil {
return err
}
ecies, err := spi.NewAsymmetricCipherFromPublicKey(eciesKey)
if err != nil {
return err
}
out, err := ecies.Process(resp.Tok.Tok)
if err != nil {
return err
}
req.Tok.Tok = out
req.Sig = nil
hash := primitives.NewHash()
raw, _ := proto.Marshal(req)
hash.Write(raw)
r, s, err := ecdsa.Sign(rand.Reader, signPriv, hash.Sum(nil))
if err != nil {
return err
}
R, _ := r.MarshalText()
S, _ := s.MarshalText()
req.Sig = &pb.Signature{Type: pb.CryptoType_ECDSA, R: R, S: S}
resp, err = ecapCient.CreateCertificatePair(context.Background(), req)
As Sergey mentioned, CreateCertificatePair requests the creation of a new certificate pair,
and according to the documentation,
During registration, the application sends a request to the certificate authority to verify the user registration and if successful, the CA responds with the user certificates and keys.
Upon successful user authentication, the application will perform user registration with the CA exactly once. If registration is attempted a second time for the same user, an error will result.
This is the reason why the second call to CreateCertificatePair is failing.
If you really want to register a user who has already been registered previously, you need to remove the temporary files ( the client enrollment certificate, enrollment key, transaction certificate chain, etc.) that were created by the CA server process, and to do that, run the following command,
rm -rf /var/hyperledger/production
/var/hyperledger/production is the directory where the certificates received from CA are stored.
Souce: Note on security functionality
CreateCertificatePair requests the creation of a new enrolment certificate pair by the ECA.
"enrolment" certificate is unique and can be created just once per user by ECA
Second call to CreateCertificatePair for the same user will lead to error.
Related
I have this piece of go code, mostly taken from here:
fmt.Println("Please enter your role: ")
fmt.Scanf("%s", &roleName)
flag.StringVar(&startURL, "start-url", "", "AWS SSO Start URL")
flag.StringVar(&accountID, "account-id", "", "AWS Account ID to fetch credentials for")
flag.Parse()
if startURL == "" || accountID == "" || roleName == "" {
flag.Usage()
os.Exit(1)
}
cfg := aws.Config{Region: "eu-west-1"}
// create sso oidc client to trigger login flow
ssooidcClient := ssooidc.NewFromConfig(cfg)
// register your client which is triggering the login flow
register, err := ssooidcClient.RegisterClient(context.TODO(), &ssooidc.RegisterClientInput{
ClientName: aws.String("sample-client-name"),
ClientType: aws.String("public"),
Scopes: []string{"sso-portal:*"},
})
if err != nil {
fmt.Println(err)
}
// authorize your device using the client registration response
deviceAuth, err := ssooidcClient.StartDeviceAuthorization(context.TODO(), &ssooidc.StartDeviceAuthorizationInput{
ClientId: register.ClientId,
ClientSecret: register.ClientSecret,
StartUrl: aws.String(startURL),
})
if err != nil {
fmt.Println(err)
}
// trigger OIDC login. open browser to login. close tab once login is done. press enter to continue
url := aws.ToString(deviceAuth.VerificationUriComplete)
fmt.Printf("If browser is not opened automatically, please open link:\n%v\n", url)
err = browser.OpenURL(url)
if err != nil {
fmt.Println(err)
}
fmt.Println("Press ENTER key once login is done")
// These lines get skipped on Windows
// also tried bufio.NewReader(os.Stdin).ReadBytes('\n')
// and fmt.Scanf("%s", &test)
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
if scanner.Err() != nil {
fmt.Println()
}
token, err := ssooidcClient.CreateToken(context.TODO(), &ssooidc.CreateTokenInput{
ClientId: register.ClientId,
ClientSecret: register.ClientSecret,
DeviceCode: deviceAuth.DeviceCode,
GrantType: aws.String("urn:ietf:params:oauth:grant-type:device_code"),
})
While on MacOS, the program waits for user input and hence the SSO login works perfectly, on Windows it gets skipped and the user does not have time to accept the login on AWS side, so the program fails. Moreover, the first prompt that asks for the users' role works correctly, so I really don't understand the second one just gets skipped ?
I use these commands to build the binary, from a MacOS machine:
GOOS=darwin go build
GOOS=windows go build
The call fmt.Scanf("%s", &roleName) returns after reading the first whitespace character after the token.
The line terminator on Windows is \r\n. The fmt.Scanf call returns after reading the \r. The \n remains in stdin. The later call to scanner.Scan() reads the remaining \n in stdin and returns immediately.
The line terminator on other systems is \n. The call fmt.Scanf returns after reading the entire line terminator. The call to scanner.Scan() waits for the user to type another line terminator.
One fix is to use the scanner for all input:
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Please enter your role: ")
if !scanner.Scan() {
// handle EOF
}
roleName = strings.TrimSpace(scanner.Text())
…
fmt.Println("Press ENTER key once login is done")
scanner.Scan()
…
I am looking for suggestions on how to use openPGP to decrypt a PGP encrypted file we receive externally. The file is placed on a Google Cloud bucket and I am planning to use a Cloud function to run the decryption.
There are several examples (this and this) on the web with Go and OpenPGP but they are limited to decrypting strings/texts and not files. The file is encrypted using a traditional PGP encrypt command.
I am trying to avoid creating a VM or asking the external agency to change the encryption process.
In your example linked you can see that it decrypts a byte slice []byte. It can be the content from an encrypted file.
You can replace the
decrypted, err := pgp.Decrypt(privEntity, encrypted)
if err != nil {
t.Error(err)
}
by
encrypted, err := ioutil.ReadFile(filename)
if err != nil {
t.Error(err)
}
decrypted, err := pgp.Decrypt(privEntity, encrypted)
if err != nil {
t.Error(err)
}
I'd like to verify a PEM certificate against an issuing chain which is also a .pem file with several certificates separated by newline characters as shown in this gist, https://gist.github.com/kurtpeek/8bf3282e344c781a20c5deadac75059f. I've tried this with Certpool.AppendCertsFromPEM as follows:
package main
import (
"crypto/x509"
"encoding/pem"
"io/ioutil"
"github.com/sirupsen/logrus"
)
func main() {
caCertPEM, err := ioutil.ReadFile("issuing_chain.pem")
if err != nil {
logrus.WithError(err).Fatal("read CA PEM file")
}
certPEM, err := ioutil.ReadFile("3007e750-e769-440b-9075-41dc2b5b1787.pem")
if err != nil {
logrus.WithError(err).Fatal("read cert PEM file")
}
block, rest := pem.Decode(certPEM)
if block == nil {
logrus.WithField("rest", rest).Fatal("Decode CA PEM")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
logrus.WithError(err).Fatal("parse certificate")
}
roots := x509.NewCertPool()
roots.AppendCertsFromPEM(caCertPEM)
chain, err := cert.Verify(x509.VerifyOptions{Roots: roots})
if err != nil {
logrus.WithError(err).Fatal("failed to verify cert")
}
logrus.Infof("issuing chain: %+v", chain)
}
However, if I run this I get the following error:
FATA[0000] failed to verify cert error="x509: certificate specifies an incompatible key usage"
exit status 1
I believe this error is returned on line 790 of https://golang.org/src/crypto/x509/verify.go:
if len(chains) == 0 {
return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
}
In other words, the Verify() method is unable to build any chains from the options provided. I've tried splitting out the intermediates (the top two in the issuing_chain.pem shown in the gist) into a separate PEM file and adding those as Intermediates to the x509.VerifyOptions, but I still get the same error.
What is the correct way to verify a certificate against an issuing chain in Go?
Your leaf certificate is for client authentication only.
$ openssl x509 -noout -text -in leaf.pem | grep -A1 'Key Usage'
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication
If this is intentional, you must specify the KeyUsages option because "an empty list means ExtKeyUsageServerAuth". You also have to go back to your version of the code that provides the intermediate certs separately:
chain, err := cert.Verify(x509.VerifyOptions{
Roots: roots,
Intermediates: inters,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
})
Try it on the playground: https://play.golang.org/p/1BNLthzu5Tz. Note that the playground requires the CurrentTime option to verify correctly. Remove this when copying elsewhere!
I'm following this documentation to upload files to GCS.
Setting Up Authentication for Server to Server Production Applications
It works in local but in production i get this error:
Post https://www.googleapis.com/upload/storage/v1/b/[bucket-name]/o?alt=json&prettyPrint=false&projection=full&uploadType=multipart: x509: failed to load system roots and no roots provided.
func UploadIMG(ctx *context.Context, file []byte, fileName string) error {
storageClient, err := storage.NewClient(*ctx)
if err != nil {
log.Fatal(err)
}
w := storageClient.Bucket(bucketName).Object(fileName).NewWriter(*ctx)
if _, err := w.Write(file); err != nil {return err}
if err := w.Close(); err != nil {return err}
oauthClient, err := google.DefaultClient(*ctx, cloudkms.CloudPlatformScope)
if err != nil {
log.Fatal(err)
}
kmsService, err := cloudkms.New(oauthClient)
if err != nil {
log.Fatal(err)
}
_ = kmsService
return nil
}
Did you actually continue with the tutorial you linked, making sure you have the correct credentials?
The error itself is likely certificate related. When it tries to do the request, it looks for root certificates on the underlying system but can't find them or open them. On for example Ubuntu, they should be under /usr/share/ca-certificates and/or /etc/ssl/certs . Make sure you have your certificates with correct privileges in order to be able to do the request you want.
as guys said in their answers, it's related to missing Certificate Authority in my dockerFile.
In my case, in alpine there is already a package utility called ca-certificates which comes with its preinstalled certs. Just needed to add the following command to my docker.
RUN apk --no-cache add ca-certificates
For any google api's you will need a root CA of trust.
Not sure of your production environment, but if you are using Docker add this line to your Dockerfile:
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
from, say a Linux build, you can see the order go will look to find the system root trust files:
https://golang.org/src/crypto/x509/root_linux.go
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
If you do not have any of these directories in your production (linux) build, then go will have no system root trust, and you will get the error you are seeing.
I'm pretty new in golang and in google cloud.
I try to write the following code and get: (perform a simple query on big-query from golang)
Error on read %v googleapi: Error 403: Access Denied: BigQuery BigQuery: No OAuth token with Google Drive scope was found., accessDenied
I read few stackoverflow items about it, but can't find any information for golang.
my code:
ctx := context.Background()
projectID := "XXXXXXXXX"
jsonPath:="XXXXX.json"
client, err := bigquery.NewClient(ctx, projectID,option.WithCredentialsFile(jsonPath))
if err != nil {
fmt.Println ("Failed to create client: %v", err)
return
}
destDatasetID:="dataset1"
destTableID:="table1"
q := client.Query("SELECT * from table1")
q.Location = "EU" // Location must match the dataset(s) referenced in query.
q.QueryConfig.Dst = client.Dataset(destDatasetID).Table(destTableID)
q.AllowLargeResults = true
fmt.Println("prepare complete")
it, err := q.Read(ctx)
if err != nil {
fmt.Println("Error on read %v",err)
return
}
code is ok, check your service account access rights as:
go to project console -> service accounts
-> create key along with big query access rights
-> finally create key and export is as json
few things to mention:
1. be conservative when giving access to service accounts (minimal access required)
2. re-name your keys in shell accordingly to avoid confusion ex: bigQueryReadOnly.json