tpm2.RSADecrypt error inconsistent attributes golang - go

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!

Related

Cannot broadcast bitcoin transaction Golang

I've encouraged an error broadcasting my bitcoin transaction here.
Error validating transaction: Error running script for input 0 referencing 78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18 at 0: Script was NOT verified successfully..
I've tried to put decoded Asm PkScript instead of PubKey in TxIn. I've tried to find similar error on sof but their steps didn't work for me. Can anyone find out what is wrong with this tx? because my vm didn't find any troubles.
Hex transaction:
0100000001181e15e7aa64ce9a21421e3b1dffe63418e6cf0959d1d847f732415e77dfb678000000008a47304402200aa339f80c705a22180c8edd4acc4baa5bc76c9e8f64852eb3cb507f027aee9c02206da34700e76df568ef018fe346bb5b9c4484506ee84740916d6c3b454c2e1d3f0141042a1b4d9533ff37cd290b95016056cacbdbbf99b5975345dc5837a95f698f8a26d74f726e2a1e62552107953595502c8078a84311690c61ace3f22644ae33a0abffffffff02d0070000000000001976a91437383464376cccaf2ae4c8a121805f45bf544e4488acc8320000000000001976a914a404271e971d58240add530813e514b0ffe45f3588ac00000000
Decoded transaction:
{
"addresses": [
"mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1",
"mkYvnmm3KUBkvVqUAYsG6A6amt5Dva4jzX"
],
"block_height": -1,
"block_index": -1,
"confirmations": 0,
"double_spend": false,
"fees": 5000,
"hash": "410f8119e9c225fc197a21ede7f9e6902f85a36010a2776dd3fdc2663072a36c",
"inputs": [
{
"addresses": [
"mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1"
],
"age": 2345496,
"output_index": 0,
"output_value": 20000,
"prev_hash": "78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18",
"script": "47304402200aa339f80c705a22180c8edd4acc4baa5bc76c9e8f64852eb3cb507f027aee9c02206da34700e76df568ef018fe346bb5b9c4484506ee84740916d6c3b454c2e1d3f0141042a1b4d9533ff37cd290b95016056cacbdbbf99b5975345dc5837a95f698f8a26d74f726e2a1e62552107953595502c8078a84311690c61ace3f22644ae33a0ab",
"script_type": "pay-to-pubkey-hash",
"sequence": 4294967295
}
],
"outputs": [
{
"addresses": [
"mkYvnmm3KUBkvVqUAYsG6A6amt5Dva4jzX"
],
"script": "76a91437383464376cccaf2ae4c8a121805f45bf544e4488ac",
"script_type": "pay-to-pubkey-hash",
"value": 2000
},
{
"addresses": [
"mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1"
],
"script": "76a914a404271e971d58240add530813e514b0ffe45f3588ac",
"script_type": "pay-to-pubkey-hash",
"value": 13000
}
],
"preference": "low",
"received": "2022-09-06T14:10:50.749940874Z",
"relayed_by": "44.204.10.232",
"size": 257,
"total": 15000,
"ver": 1,
"vin_sz": 1,
"vout_sz": 2,
"vsize": 257
}
func main() {
connCfg := &rpcclient.ConnConfig{ //smth here
}
client, err := rpcclient.New(connCfg, nil)
if err != nil {
log.Fatal(err)
}
defer client.Shutdown()
utxoMap := make(map[string]string)
utxoMap["mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1"] = "78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18"
rawTx, err := CreateRawTx("mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1", "mkYvnmm3KUBkvVqUAYsG6A6amt5Dva4jzX", 2000, utxoMap, client)
if err != nil {
println(err.Error())
}
signedTx, err := Sign(rawTx, "private key here")
if err != nil {
println(err.Error())
}
fmt.Println(signedTx)
}
type UTXO struct {
previousTxID string
pubKeyScript string
Asm string
Amount decimal.Decimal
}
func GetUTXO(utxoMap map[string]string, address string, client *rpcclient.Client) (utxo UTXO, err error) {
// unmarshal it, and extract necessary data
hash, _ := chainhash.NewHashFromStr(utxoMap[address])
tx, err := client.GetRawTransactionVerbose(hash)
if err != nil {
return utxo, errors.Wrapf(err, "GetUTXO.GetRawTransactionVerbose")
}
pubKeyScript := tx.Vout[0].ScriptPubKey.Hex
previousTxID := utxoMap[address]
amount := decimal.NewFromFloat(tx.Vout[0].Value)
asm := tx.Vout[0].ScriptPubKey.Hex
return UTXO{
previousTxID: previousTxID,
pubKeyScript: pubKeyScript,
Asm: asm,
Amount: amount,
}, nil
}
func GetPayToAddrScript(address string) []byte {
rcvAddress, _ := btcutil.DecodeAddress(address, &chaincfg.TestNet3Params)
rcvScript, _ := txscript.PayToAddrScript(rcvAddress)
return rcvScript
}
type TXRef struct {
TXHash string
TXOutputN int
}
// get private key
func getKeyAddressFromPrivateKey(privateKey string, conf *chaincfg.Params) (*btcec.PrivateKey, string, error) {
newWif, err := btcutil.DecodeWIF(privateKey)
if err != nil {
return nil, "", err
}
publicKey := newWif.PrivKey.PubKey().SerializeUncompressed()
address, err := btcutil.NewAddressPubKeyHash(btcutil.Hash160(publicKey), conf)
if err != nil {
return nil, "", err
}
return newWif.PrivKey, address.EncodeAddress(), nil
}
// debug signing function
func Sign(rawTx, privateKey string) (string, error) {
var signTx wire.MsgTx
err := json.Unmarshal([]byte(rawTx), &signTx)
if err != nil {
return "", err
}
myPrivateKey, address, err := getKeyAddressFromPrivateKey(privateKey, &chaincfg.TestNet3Params)
fmt.Println("address ", address)
if err != nil {
return "", err
}
txScript := GetPayToAddrScript(address)
for i := 0; i < len(signTx.TxIn); i++ {
sig, err := txscript.SignatureScript(
&signTx, // The tx to be signed.
i, // The index of the txin the signature is for.
txScript, // The other half of the script from the PubKeyHash.
txscript.SigHashAll, // The signature flags that indicate what the sig covers.
myPrivateKey, // The key to generate the signature with.
false) // The compress sig flag. This saves space on the blockchain.
if err != nil {
return "", err
}
//refer from this link for sign multiple inputs https://bitcoin.stackexchange.com/questions/41209/how-to-sign-a-transaction-with-multiple-inputs
signTx.TxIn[i].SignatureScript = sig
//Validate signature
flags := txscript.StandardVerifyFlags
vm, err := txscript.NewEngine(txScript, &signTx, i, flags, nil, nil, signTx.TxOut[0].Value, nil)
if err != nil {
return "", err
}
if err := vm.Execute(); err != nil {
return "", err
}
}
// return signed tx
var signedTx bytes.Buffer
signTx.Serialize(&signedTx)
hexSignedTx := hex.EncodeToString(signedTx.Bytes())
return hexSignedTx, nil
}
// CreateBtcRawTx create raw tx for sending btc
func CreateRawTx(from string, to string, amount int64, utxoMap map[string]string, client *rpcclient.Client) (string, error) {
amountInt := amount
var feeBitcoin int64 = 5000
spendAmount := amountInt + feeBitcoin
utxo, err := GetUTXO(utxoMap, from, client)
changeAmount := utxo.Amount.Shift(8).IntPart() - spendAmount
// create new empty transaction
redemTx := wire.NewMsgTx(wire.TxVersion)
// create multiple txIns
hash, err := chainhash.NewHashFromStr(utxo.previousTxID)
if err != nil {
fmt.Printf("could not get hash from transaction ID: %v", err)
return "", err
}
outPoint := wire.NewOutPoint(hash, 0)
txIn := wire.NewTxIn(outPoint, nil, nil)
redemTx.AddTxIn(txIn)
// create TxOut
rcvScript := GetPayToAddrScript(to)
txOut := wire.NewTxOut(amountInt, rcvScript)
redemTx.AddTxOut(txOut)
// create TxOut for change address, in this case, change address is sender itself
if changeAmount > 0 {
// return change BTC to its own address
rcvChangeAddressScript := GetPayToAddrScript(from)
txOut := wire.NewTxOut(changeAmount, rcvChangeAddressScript)
redemTx.AddTxOut(txOut)
}
encodedTx, err := json.Marshal(redemTx)
if err != nil {
return "", err
}
// return raw tx in hex format
return string(encodedTx), nil
}
my bitcoin wallet: mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1
last transaction on the wallet (hash): 78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18

Failed Unmarshal for xxx invalid character '{' after top-level value

Failed Unmarshal for LP name invalid character '{' after top-level value
package main
import (...)
type hostInfo struct {
Name string
}
var b bytes.Buffer
var c bytes.Buffer
var tmphostInfo hostInfo
var result map[string]interface{}
func main() {
keypath := os.Args[1]
hostiplist := []string {"192.168.1.150","192.168.1.151","192.168.1.152","192.168.1.153"}
port := "22"
key,err := ioutil.ReadFile(keypath)
if err != nil {
log.Fatalf("Unable to read private key: %v", err)
}
signer,err:=ssh.ParsePrivateKey(key)
if err != nil {
log.Fatalf("Unable to parse private key: %v",err)
}
var conn *ssh.Client
config := &ssh.ClientConfig{
User: "support",
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: 5*time.Second,
}
for _,hostip := range hostiplist {
conn,err = ssh.Dial("tcp",net.JoinHostPort(hostip,port),config)
if err != nil {
log.Fatalf("unable to connect: %v",err)
}
defer conn.Close()
session1,err:=conn.NewSession()
if err != nil {
log.Fatalf("unable to connect: %v",err)
}
defer session1.Close()
session1.Stdout = &b
if err := session1.Run("some mongo query"); err != nil {
log.Fatal("Failed to run:sess1 " + err.Error())
}
tmphostInfo=hostInfo{}
fmt.Printf("tmphostInfo: %v , ip : %s",tmphostInfo.Name,hostip)
err1 := json.Unmarshal([]byte(""),&tmphostInfo)
if err1 != nil {
log.Fatalf("Failed Unmarshal for LP name %v for IP %s",err1,hostip)
}
session2,err:=conn.NewSession()
session2.Stdout = &c
if err := session2.Run("another mongo query"); err != nil {
log.Fatal("Failed to run:sess2 " + err.Error())
}
err2 := json.Unmarshal([]byte(c.String()),&result)
if err2 != nil {
log.Fatalf("Failed Unmarshal for Customer name %v",err2)
}
//fmt.Println(c.String())
custmap := result["customer"].(map[string]interface{})
//fmt.Println(birds)
var LPname string
for key, value := range custmap {
// Each value is an interface{} type, that is type asserted as a string
//fmt.Println(key, value.(string))
if key == "name" {
LPname=value.(string)
}
}
fmt.Println(hostip,tmphostInfo.Name,LPname)
f, err := os.OpenFile("/tmp/supportip.csv", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
if _, err := f.Write([]byte(hostip+","+tmphostInfo.Name+","+LPname+"\n")); err != nil {
log.Fatal(err)
}
if err := f.Close(); err != nil {
log.Fatal(err)
}
}
}
go run scan.go /path/to/key results in
tmphostInfo: {} , ip : 192.168.1.150 10.45.9.141 servername1 DFIDorg
tmphostInfo: {} , ip : 192.168.1.151 2021/12/10 15:07:36 Failed Unmarshal for LP name invalid character '{' after top-level value for 192.168.1.151
exit status 1
The unmarshal for both queries result for first array element "192.168.1.150" is successful but fails on second and rest of items
The json string for first query looks like below
{ "name" : "john doe" }
result of second query looks like
{
"customer" : {
"address1" : "ktm",
"secret_key" : "12237918f0d441d25fb",
"address2" : "",
"name" : "KUKL Limited",
"phone" : "12345"
}
}
I had to reset the bytes.Buffer variable right after the for loop start, the issue was that the result pulled from ssh execution had been appended to buffer which could not be deserialized
for _,hostip := range hostiplist {
b.Reset()
c.Reset()

AES-256-GCM Encryption from Ruby & Decryption with Golang

I have an encryption in Ruby with aes-256-gcm
require 'openssl'
key = "972ec8dd995743d981417981ac2f30db"
iv = "6a825c25ea74"
auth_data = "73f6828fc5be"
plaintext = "John Doe play foo bar"
cipher = OpenSSL::Cipher.new('aes-256-gcm')
cipher.encrypt
cipher.iv = iv
cipher.key = key
cipher.auth_data = auth_data
cipherText = cipher.update(plaintext) + cipher.final
authTag = cipher.auth_tag
hexString = (cipherText + iv + authTag).unpack('H*').first
the hextString result looks like
fa03a24cad007ceaadc34c22edff943cb58fe514ed36613832356332356561373425f6bc5724b956daae151c8d78a21263
I want to decrypt it in Go
key := "972ec8dd995743d981417981ac2f30db"
iv := "6a825c25ea74"
authData := "73f6828fc5be"
hexString, _ := hex.DecodeString("fa03a24cad007ceaadc34c22edff943cb58fe514ed36613832356332356561373425f6bc5724b956daae151c8d78a21263")
block, err := aes.NewCipher([]byte(key))
if err != nil {
panic(err.Error())
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
plaintext, err := aesgcm.Open(nil, []byte(iv), hexString, []byte(authData))
if err != nil {
panic(err.Error())
}
I got cipher: message authentication failed.
and Also I don't get the point about authData in golang, I can't fine it in here https://golang.org/pkg/crypto/cipher/#NewGCM
The nonce (iv) does not belong in the middle of the ciphertext. The hex-encoded output you want here from the ruby example is only the cipherText + authTag. Since the nonce must be sent along with the ciphertext, it is common to prefix the ciphertext with the nonce if you so choose, but you must trim that off before deciphering the message. (Also note that your key, iv and auth_data values appear to be hex strings, but they are being used as raw bytes which may be adding to some of the confusion).
Re-arranging the bytes of the message to prepend the nonce, gives us this example: https://play.golang.org/p/YV5FugSyM5_G
key := []byte("972ec8dd995743d981417981ac2f30db")
authData := []byte("73f6828fc5be")
msg, err := hex.DecodeString("366138323563323565613734fa03a24cad007ceaadc34c22edff943cb58fe514ed25f6bc5724b956daae151c8d78a21263")
block, err := aes.NewCipher([]byte(key))
if err != nil {
log.Fatal(err)
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
log.Fatal(err)
}
sz := aesgcm.NonceSize()
nonce, cipherText := msg[:sz], msg[sz:]
pt, err := aesgcm.Open(nil, nonce, cipherText, authData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q\n", pt)
"John Doe play foo bar"
This is what worked for me. I originally used the attr_encrypted gem to encrypt the information.
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
"log"
)
func main() {
// data: "7621276423"
// encrypted_data: "Hz1HXFTfSyucPvy3iDoY1F4O5YmAx2skRa4="
// encrypted_data_iv: "Ezk8f3+944gs4x5E"
// license_key: "iUPGMBmppYA92kbciS5fIUe7gRcx6G025haOeAmEjU4="
cipherText, err := base64.StdEncoding.DecodeString("Hz1HXFTfSyucPvy3iDoY1F4O5YmAx2skRa4=")
nonce, err := base64.StdEncoding.DecodeString("Ezk8f3+944gs4x5E")
key, err := base64.StdEncoding.DecodeString("iUPGMBmppYA92kbciS5fIUe7gRcx6G025haOeAmEjU4=")
block, err := aes.NewCipher([]byte(key))
if err != nil {
log.Fatal(err)
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
log.Fatal(err)
}
pt, err := aesgcm.Open(nil, nonce, cipherText, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q\n", pt)
}
// "123456789"

Parsing X509 certificate in 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

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