Parsing X509 certificate in Go - go

I am having the following function, which reads an X509 certificate.
certCerFile,err := os.Open("certificate.pem")
if err != nil {
log.Fatal(err)
}
derBytes := make([]byte,1000)
count,err:=certCerFile.Read(derBytes)
if err != nil {
log.Fatal(err)
}
certCerFile.Close()
// trim the bytes to actual length in call
cert,err := x509.ParseCertificate(derBytes[0:count])
if err != nil {
log.Fatal(err)
}
fmt.Printf("Name %s\n", cert.Subject.CommonName)
fmt.Printf("Not before %s\n", cert.NotBefore.String())
fmt.Printf("Not after %s\n", cert.NotAfter.String())
I face the following error:
asn1: structure error: tags don't match (16 vs {class:0 tag:13 length:45 isCompound:true}) {optional:false explicit:false application:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} certificate #2
That's how I generate X509:
random := rand.Reader
var key rsa.PrivateKey
loadKey("private.key",&key)
now:= time.Now()
then := now.Add(60 * 60 * 24 * 365 * 1000 * 1000 * 1000)
template:= x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "borscht.com",
Organization: []string{"Borscht Systems AG"},
},
NotBefore:now,
NotAfter:then,
SubjectKeyId: []byte{1,2,3,4},
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
BasicConstraintsValid:true,
IsCA:true,
DNSNames:[]string{"borscht.com","localhost"},
}
derBytes,err:=x509.CreateCertificate(random, &template, &template,&key.PublicKey,&key)
if err != nil {
log.Fatal(err)
}
certCerFile,err :=os.Create("certificate.cer")
if err != nil {
log.Fatal(err)
}
certCerFile.Write(derBytes)
certCerFile.Close()
certPemFile, err := os.Create("certificate.pem")
if err != nil {
log.Fatal(err)
}
I just don't understand what might be wrong.

I made a mistake myself. Parse pem instead of cer file. Replaced and everything is fine

Related

tpm2.RSADecrypt error inconsistent attributes golang

I use tpm2 to encrypt and decrypt data with RSA. Encrypt function work well but cannot decrypt.
First, I create RSA Key and persistence it:
var (
publicKeyTemplate = tpm2.Public{
Type: tpm2.AlgRSA,
NameAlg: tpm2.AlgSHA256,
Attributes: tpm2.FlagFixedTPM | tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth | tpm2.FlagRestricted | tpm2.FlagDecrypt | tpm2.FlagNoDA,
AuthPolicy: nil,
RSAParameters: &tpm2.RSAParams{
Symmetric: &tpm2.SymScheme{
Alg: tpm2.AlgAES,
KeyBits: 256,
Mode: tpm2.AlgCFB,
},
KeyBits: 2048,
},
}
)
func createRSAKey(rwc io.ReadWriteCloser, ownerPassword string, persistentHandler tpmutil.Handle) {
srkHandle, publicKey, err := tpm2.CreatePrimary(
rwc,
tpm2.HandleOwner,
tpm2.PCRSelection{},
"",
ownerPassword,
publicKeyTemplate)
log.Println(publicKey)
err = tpm2.EvictControl(rwc, "", tpm2.HandleOwner, srkHandle, persistentHandler)
if err != nil {
log.Fatal(err)
}
}
Then I encrypt data with tpm2.RSAEncrypt, it works well
rwc, err := tpm2.OpenTPM()
if err != nil {
log.Fatal(err)
}
ownerPassword := "123456"
persistentHandler := tpmutil.Handle(0x81000020)
// createRSAKey(rwc, ownerPassword, persistentHandler)
en, err := tpm2.RSAEncrypt(rwc, persistentHandler, []byte("abcdef"), &tpm2.AsymScheme{
Alg: tpm2.AlgOAEP,
Hash: tpm2.AlgSHA256,
}, "label")
log.Printf("Encrypted: %x\n", en)
if err != nil {
log.Fatal(err)
}
But I cannot decrypt the encrypted data. It shows error code 0x2 : inconsistent attributes
de, err := tpm2.RSADecrypt(rwc, persistentHandler, ownerPassword, en, &tpm2.AsymScheme{
Alg: tpm2.AlgOAEP,
Hash: tpm2.AlgSHA256,
}, "label")
log.Printf("Decrypted: %x\n", string(de))
if err != nil {
log.Fatal(err)
}
What 's wrong in my code? Thanks very much!

Golang Opc UA Client Implementation with Certificate

I am trying to connect my local Kepware OPC UA server with certificate. OPC UA server security info:
In golang app , I use "github.com/gopcua/opcua/ua" opc client package. I create key pair and I give them path to variables and used them in config:
opts := []opcua.Option{
opcua.SecurityPolicy(relatedConnection.SecurityPolicy),
opcua.SecurityModeString(relatedConnection.SecurityMode),
opcua.CertificateFile(certFile),
opcua.PrivateKeyFile(keyFile),
opcua.AutoReconnect(true),
opcua.ReconnectInterval(time.Second * 5),
opcua.RequestTimeout(time.Second * 3),
}
When security policy and mode are none, I can connect to the server without any problem. When I chose these security policies I don't know how to implement code or ssl key pair to connect server.
In order to use any security policy above None/None or to use a username/password login, you need to either have an existing X.509 certificate or generate one yourself.
Note, the certificate comes in two parts, a public certificate and a private key. You need both. The public certificate will be sent to the Kepware server while the private key will stay with the client and be used for encryption and decryption.
endpoints, err := opcua.GetEndpoints(context.Background(), cfg.Endpoint)
if err != nil {
return nil, fmt.Errorf("OPC GetEndpoints: %w", err)
}
policy := ua.SecurityPolicyURINone // Replace this with a constant of your security policy
mode := ua.MessageSecurityModeNone // Replace this with a constant of your security mode
ep := opcua.SelectEndpoint(endpoints, policy, mode)
c, err := generateCert() // This is where you generate the certificate
if err != nil {
return nil, fmt.Errorf("generateCert: %w", err)
}
pk, ok := c.PrivateKey.(*rsa.PrivateKey) // This is where you set the private key
if !ok {
return nil, fmt.Errorf("invalid private key")
}
cert := c.Certificate[0]
opts := []opcua.Option{
opcua.SecurityPolicy(policy),
opcua.SecurityMode(mode),
opcua.PrivateKey(pk),
opcua.Certificate(cert), // Set the certificate for the OPC UA Client
opcua.AuthUsername(cfg.Username, cfg.Password), // Use this if you are using username and password
opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeUserName),
opcua.SessionTimeout(30 * time.Minute),
opcua.AutoReconnect(true),
opcua.ReconnectInterval(time.Second * 10),
opcua.Lifetime(30 * time.Minute),
opcua.RequestTimeout(3 * time.Second),
}
Use the following to generate the X.509 certificate.
func generateCert() (*tls.Certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, fmt.Errorf("failed to generate private key: %s", err)
}
notBefore := time.Now()
notAfter := notBefore.Add(365 * 24 * time.Hour) // 1 year
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, fmt.Errorf("failed to generate serial number: %s", err)
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Test Client"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageContentCommitment | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
host := "urn:testing:client"
if ip := net.ParseIP(host); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, host)
}
if uri, err := url.Parse(host); err == nil {
template.URIs = append(template.URIs, uri)
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
if err != nil {
return nil, fmt.Errorf("failed to create certificate: %s", err)
}
certBuf := bytes.NewBuffer(nil)
if err := pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
return nil, fmt.Errorf("failed to encode certificate: %s", err)
}
keyBuf := bytes.NewBuffer(nil)
if err := pem.Encode(keyBuf, pemBlockForKey(priv)); err != nil {
return nil, fmt.Errorf("failed to encode key: %s", err)
}
cert, err := tls.X509KeyPair(certBuf.Bytes(), keyBuf.Bytes())
return &cert, err
}
Here is an example directly from the gopcua project:
https://github.com/gopcua/opcua/blob/main/examples/crypto/generate_cert.go

Decrypting a non ASCII armored PGP file in Go

Is it possible to decrypt binary .PGP file with Go's "golang.org/x/crypto/openpgp" library?
The following code works with an armored ASCII encoded file but throws EOF error with a binary PGP file. Is there a similar function to armor.Decode() that allows for the binary file to be decrypted?
func DecryptFile(encryptedFilePath string, decryptedFilePath string) error {
pubKey := decodePublicKey()
privKey := decodePrivateKey()
entity := createEntityFromKeys(pubKey, privKey)
file := readFile(encryptedFilePath)
block, err := armor.Decode(file)
if err != nil {
log.Printf("Error reading OpenPGP Armor: %s", err)
return err
}
if block.Type != "Message" {
log.Println("Invalid message type")
return err
}
var entityList openpgp.EntityList
entityList = append(entityList, entity)
messageDetails, err := openpgp.ReadMessage(block.Body, entityList, nil, nil)
if err != nil {
log.Printf("Error reading message: %s", err)
return err
}
compressed, err := gzip.NewReader(messageDetails.UnverifiedBody)
if err != nil {
log.Printf("Invalid compression level: %s", err)
return err
}
defer compressed.Close()
buffer := bytes.NewBuffer(nil)
n, err := io.Copy(buffer, compressed)
if err != nil {
log.Printf("Error reading encrypted file: %s", err)
return err
}
err = ioutil.WriteFile(decryptedFilePath, buffer.Bytes(), 0644)
if err != nil {
log.Println(err)
return err
}
log.Printf("Decrypted %d bytes\n", n)
return nil
}
I encountered the same exact problem with PGP, also got EOF on my first trial.
The encrypted file is in binary(.pgp)
The private/public key in key ring armored file(.asc) like this:
----BEGIN PGP PUBLIC KEY BLOCK-----
-----END PGP PRIVATE KEY BLOCK-----
Here is the code that I use:
keyRing, err := os.Open("keyArmoredFile.asc")
if err != nil {
log.Fatal(err)
}
entityList, err := openpgp.ReadArmoredKeyRing(keyRing)
if err != nil {
log.Fatal(err)
}
entity := entityList[0]
passphraseByte := []byte("password")
err = entity.PrivateKey.Decrypt(passphraseByte)
if err != nil {
log.Fatal(err)
}
for _, subkey := range entity.Subkeys {
subkey.PrivateKey.Decrypt(passphraseByte)
}
encryptedContent, err := os.Open("encryptedFile.pgp")
if err != nil {
log.Fatal(err)
}
md, err := openpgp.ReadMessage(encryptedContent, entityList, nil, nil)
if err != nil {
log.Fatal(err)}
bytes, err := ioutil.ReadAll(md.UnverifiedBody)
if err != nil {
log.Fatal(err)
}
// decryption result
decStr := string(bytes)
Reference:
https://gist.github.com/stuart-warren/93750a142d3de4e8fdd2

Golang rsa x509 ParsePKIXPublicKey error

I'm getting some strange situation with parsing just-created rsa keys.
In this part I generate new pair and write into file:
rsaKey,err:= rsa.GenerateKey(rand.Reader,2048)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
publicKey := rsaKey.PublicKey
outFile, err := os.Create("./private.pem")
defer outFile.Close()
var privateKey = &pem.Block{
Type: "PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
}
err = pem.Encode(outFile, privateKey)
asn1Bytes, err := asn1.Marshal(publicKey)
var pemkey = &pem.Block{
Type: "PUBLIC KEY",
Bytes: asn1Bytes,
}
pemfile, err := os.Create("./public.pem")
defer pemfile.Close()
err = pem.Encode(pemfile, pemkey)
Next step is reading key from file and parse it:
data, err := ioutil.ReadFile("./public.pem")
block, _ :=pem.Decode(data)
res,err := x509.ParsePKIXPublicKey(block.Bytes)
fmt.Print(err)
But x509.ParsePKIXPublicKey(block.Bytes) return error:
asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:257 isCompound:false}) {optional:false explicit:false application:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} AlgorithmIdentifier #4
playground example
https://play.golang.org/p/djlK8lO5_E2
Please help me solve this issue.

JWT key is invalid

I am following this example https://www.youtube.com/watch?v=eVlxuST7dCA to make a jwt auth. When I run the code below I get "Key is invalid" error. When I try printing tokenString it is empty. The GitHub to this sample is https://github.com/potatogopher/jwt-go-example/blob/master/server.go Why am I getting invalid error?
var privateKey []byte
privateKey, err := ioutil.ReadFile("demo.rsa")
token := jwt.New(jwt.GetSigningMethod("RS256"))
tokenString, err := token.SignedString(privateKey)
fmt.Println("TOKEN:", tokenString)
I think the example code you're referring to uses an outdated API of jwt-go. The RS256 signing method requires the key to be a rsa.PrivateKey and not a byte buffer. This means, that the private key first has to be parsed using the jwt.ParseRSAPrivateKeyFromPEMfunction.
I've updated your example below:
func main() {
tokenString, err := createSignedTokenString()
if err != nil {
panic(err)
}
fmt.Printf("Signed token string:\n%v\n", tokenString)
token, err := parseTokenFromSignedTokenString(tokenString)
if err != nil {
panic(err)
}
fmt.Printf("Parsed token valid = %v, raw token:\n%v\n", token.Valid, token.Raw)
}
func createSignedTokenString() (string, error) {
privateKey, err := ioutil.ReadFile("demo.rsa")
if err != nil {
return "", fmt.Errorf("error reading private key file: %v\n", err)
}
key, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey)
if err != nil {
return "", fmt.Errorf("error parsing RSA private key: %v\n", err)
}
token := jwt.New(jwt.SigningMethodRS256)
tokenString, err := token.SignedString(key)
if err != nil {
return "", fmt.Errorf("error signing token: %v\n", err)
}
return tokenString, nil
}
func parseTokenFromSignedTokenString(tokenString string) (*jwt.Token, error) {
publicKey, err := ioutil.ReadFile("demo.rsa.pub")
if err != nil {
return nil, fmt.Errorf("error reading public key file: %v\n", err)
}
key, err := jwt.ParseRSAPublicKeyFromPEM(publicKey)
if err != nil {
return nil, fmt.Errorf("error parsing RSA public key: %v\n", err)
}
parsedToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return key, nil
})
if err != nil {
return nil, fmt.Errorf("error parsing token: %v", err)
}
return parsedToken, nil
}
You need to create the private key with this command: openssl genrsa -out demo.rsa
If you dont want to do that, you can also use the hmac signing method where you only have to supply a secret key/string.
Example:
key := []byte("test")
token := jwt.New(jwt.SigningMethodHS256)
tokenString, err := token.SignedString(key)
fmt.Println("TOKEN:", tokenString)

Resources