diff --git a/crypto/aes.go b/crypto/aes.go index b3ce4ba..1c259bf 100644 --- a/crypto/aes.go +++ b/crypto/aes.go @@ -31,6 +31,7 @@ import ( "crypto/rand" "crypto/rsa" "crypto/sha256" + "crypto/subtle" "encoding/binary" "errors" "fmt" @@ -63,6 +64,7 @@ type AESKey struct { logger Logger strictWipe bool tpmKey *tpm.Key + tpmHMAC *tpm.Key } func (k *AESKey) Logger() Logger { @@ -114,11 +116,30 @@ func CreateAESMasterKey(opts ...Option) (MasterKey, error) { key.strictWipe = opt.strictWipe mk := &AESMasterKey{key} if opt.tpm != nil { - tpmkey, err := opt.tpm.CreateKey() - if err != nil { - return nil, err + switch opt.alg { + case AES256WithTPMRSA2048: + tpmkey, err := opt.tpm.CreateKey() + if err != nil { + return nil, err + } + mk.tpmKey = tpmkey + + case AES256WithTPMAESHMAC: + tpmkey, err := opt.tpm.CreateKey(tpm.WithAES(256)) + if err != nil { + return nil, err + } + tpmHMAC, err := opt.tpm.CreateKey(tpm.WithHMAC(256)) + if err != nil { + return nil, err + } + mk.AESKey = aesKeyFromBytes(make([]byte, 64)) + mk.tpmKey = tpmkey + mk.tpmHMAC = tpmHMAC + + default: + return nil, fmt.Errorf("invalid alg for tpm: %d", opt.alg) } - mk.tpmKey = tpmkey } return mk, nil } @@ -152,7 +173,7 @@ func ReadAESMasterKey(passphrase []byte, file string, opts ...Option) (MasterKey if !str.ReadUint8(&version) { return nil, ErrDecryptFailed } - if version != 1 && version != 3 { + if version != 1 && version != 3 && version != 4 { opt.logger.Debugf("ReadMasterKey: unexpected version: %d", version) return nil, ErrDecryptFailed } @@ -160,7 +181,7 @@ func ReadAESMasterKey(passphrase []byte, file string, opts ...Option) (MasterKey opt.logger.Error("ReadMasterKey: TPM option selected but master key was created without TPM") return nil, ErrDecryptFailed } - if version == 3 && opt.tpm == nil { + if (version == 3 || version == 4) && opt.tpm == nil { opt.logger.Error("ReadMasterKey: master key was created with TPM but TPM option not selected") return nil, ErrDecryptFailed } @@ -193,9 +214,10 @@ func ReadAESMasterKey(passphrase []byte, file string, opts ...Option) (MasterKey return nil, ErrDecryptFailed } var key *AESKey - if version == 1 { + switch version { + case 1: key = aesKeyFromBytes(mkBytes) - } else { // version == 3 + case 3: str := cryptobyte.String(mkBytes) var length uint16 if !str.ReadUint16(&length) { @@ -223,6 +245,30 @@ func ReadAESMasterKey(passphrase []byte, file string, opts ...Option) (MasterKey } key = aesKeyFromBytes(decKey) key.tpmKey = tpmKey + + case 4: + str := cryptobyte.String(mkBytes) + var aesCtx, hmacCtx []byte + if !str.ReadUint16LengthPrefixed((*cryptobyte.String)(&aesCtx)) { + return nil, ErrDecryptFailed + } + if !str.ReadUint16LengthPrefixed((*cryptobyte.String)(&hmacCtx)) { + return nil, ErrDecryptFailed + } + tpmKey, err := opt.tpm.UnmarshalKey(aesCtx) + if err != nil { + return nil, err + } + tpmHMAC, err := opt.tpm.UnmarshalKey(hmacCtx) + if err != nil { + return nil, err + } + key = aesKeyFromBytes(make([]byte, 64)) + key.tpmKey = tpmKey + key.tpmHMAC = tpmHMAC + + default: + return nil, fmt.Errorf("unexpected master key version: %d", version) } key.logger = opt.logger key.strictWipe = opt.strictWipe @@ -260,7 +306,7 @@ func (mk AESMasterKey) Save(passphrase []byte, file string) error { if mk.tpmKey == nil { version = 1 payload = mk.key() - } else { + } else if mk.tpmHMAC == nil { version = 3 buf := cryptobyte.NewBuilder(nil) // encKey, err := mk.tpmKey.Encrypt(mk.key()) @@ -282,6 +328,29 @@ func (mk AESMasterKey) Save(passphrase []byte, file string) error { mk.Logger().Debug(err) return ErrEncryptFailed } + } else { + version = 4 + aesCtx, err := mk.tpmKey.Marshal() + if err != nil { + mk.Logger().Debug(err) + return ErrEncryptFailed + } + hmacCtx, err := mk.tpmHMAC.Marshal() + if err != nil { + mk.Logger().Debug(err) + return ErrEncryptFailed + } + buf := cryptobyte.NewBuilder(nil) + buf.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(aesCtx) + }) + buf.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(hmacCtx) + }) + if payload, err = buf.Bytes(); err != nil { + mk.Logger().Debug(err) + return ErrEncryptFailed + } } encMasterKey := gcm.Seal(nonce, nonce, payload, nil) buf := cryptobyte.NewBuilder([]byte{version}) @@ -304,11 +373,22 @@ func (mk AESMasterKey) Save(passphrase []byte, file string) error { } func (k AESKey) key() []byte { + if k.tpmHMAC != nil { + // This should never happen. + panic("key() called with AES256WithTPMAESHMAC") + } return k.xor(k.maskedKey) } // Hash returns the HMAC-SHA256 hash of b. func (k AESKey) Hash(b []byte) []byte { + if k.tpmHMAC != nil { + h, err := k.tpmHMAC.HMAC(b) + if err != nil { + panic(err) + } + return h + } mac := hmac.New(sha256.New, k.key()[32:]) mac.Write(b) return mac.Sum(nil) @@ -322,13 +402,23 @@ func (k AESKey) Decrypt(data []byte) ([]byte, error) { return nil, ErrDecryptFailed } version, data := data[0], data[1:] - if version != 3 { - return nil, ErrDecryptFailed - } encData, data := data[:len(data)-sigSize], data[len(data)-sigSize:] - sig := data[:sigSize] - hashed := sha256.Sum256(encData) - if err := rsa.VerifyPKCS1v15(k.tpmKey.Public().(*rsa.PublicKey), crypto.SHA256, hashed[:], sig); err != nil { + switch version { + case 3: + sig := data[:sigSize] + hashed := sha256.Sum256(encData) + if err := rsa.VerifyPKCS1v15(k.tpmKey.Public().(*rsa.PublicKey), crypto.SHA256, hashed[:], sig); err != nil { + return nil, ErrDecryptFailed + } + case 4: + h, err := k.tpmHMAC.HMAC(encData) + if err != nil { + return nil, ErrDecryptFailed + } + if subtle.ConstantTimeCompare(h, data[:sigSize]) != 1 { + return nil, ErrDecryptFailed + } + default: return nil, ErrDecryptFailed } return k.tpmKey.Decrypt(nil, encData, nil) @@ -371,18 +461,34 @@ func (k AESKey) Decrypt(data []byte) ([]byte, error) { // Encrypt encrypts data using the key. func (k AESKey) Encrypt(data []byte) ([]byte, error) { if k.tpmKey != nil { - // encData, err := k.tpmKey.Encrypt(data) - encData, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, k.tpmKey.Public().(*rsa.PublicKey), data, nil) + if k.tpmHMAC == nil { // version 3 + // encData, err := k.tpmKey.Encrypt(data) + encData, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, k.tpmKey.Public().(*rsa.PublicKey), data, nil) + if err != nil { + return nil, ErrEncryptFailed + } + hashed := sha256.Sum256(encData) + sig, err := k.tpmKey.Sign(nil, hashed[:], crypto.SHA256) + if err != nil { + return nil, ErrEncryptFailed + } + out := make([]byte, 1+len(encData)+len(sig)) + out[0] = 3 // version + copy(out[1:], encData) + copy(out[1+len(encData):], sig) + return out, nil + } + // version 4 + encData, err := k.tpmKey.Encrypt(data) if err != nil { return nil, ErrEncryptFailed } - hashed := sha256.Sum256(encData) - sig, err := k.tpmKey.Sign(nil, hashed[:], crypto.SHA256) + sig, err := k.tpmHMAC.HMAC(encData) if err != nil { return nil, ErrEncryptFailed } out := make([]byte, 1+len(encData)+len(sig)) - out[0] = 3 // version + out[0] = 4 // version copy(out[1:], encData) copy(out[1+len(encData):], sig) return out, nil @@ -461,6 +567,9 @@ func (k AESKey) NewKey() (EncryptionKey, error) { } func (k AESKey) keysize() int { + if k.tpmHMAC != nil { + return 113 // 1 (version) + 80 (iv + encrypted 64-byte key) + 32 (HMAC-SHA256 tag) + } if k.tpmKey != nil { return 2*k.tpmKey.Bits()/8 + 1 } diff --git a/crypto/aes_test.go b/crypto/aes_test.go index 3a7462b..38cddbe 100644 --- a/crypto/aes_test.go +++ b/crypto/aes_test.go @@ -78,26 +78,60 @@ func TestTPMAESMasterKey(t *testing.T) { } defer tpm.Close() - mk, err := CreateAESMasterKey(WithTPM(tpm)) - if err != nil { - t.Fatalf("CreateMasterKey: %v", err) - } - defer mk.Wipe() - if err := mk.Save(passphrase, keyFile); err != nil { - t.Fatalf("mk.Save: %v", err) - } + t.Run("AES256WithTPMRSA2048", func(t *testing.T) { + mk, err := CreateAESMasterKey(WithTPM(tpm)) + if err != nil { + t.Fatalf("CreateMasterKey: %v", err) + } + defer mk.Wipe() + if err := mk.Save(passphrase, keyFile); err != nil { + t.Fatalf("mk.Save: %v", err) + } - mk2, err := ReadAESMasterKey(passphrase, keyFile, WithTPM(tpm)) - if err != nil { - t.Fatalf("ReadMasterKey(%q): %v", passphrase, err) - } - defer mk2.Wipe() - if got, want := mk2, mk; !reflect.DeepEqual(want.(*AESMasterKey).key(), got.(*AESMasterKey).key()) { - t.Errorf("Mismatch keys: %v != %v", want.(*AESMasterKey).key(), got.(*AESMasterKey).key()) - } - if _, err := ReadAESMasterKey([]byte("bar"), keyFile); err == nil { - t.Errorf("ReadMasterKey('bar') should have failed, but didn't") - } + mk2, err := ReadAESMasterKey(passphrase, keyFile, WithTPM(tpm)) + if err != nil { + t.Fatalf("ReadMasterKey(%q): %v", passphrase, err) + } + defer mk2.Wipe() + if got, want := mk2, mk; !reflect.DeepEqual(want.(*AESMasterKey).key(), got.(*AESMasterKey).key()) { + t.Errorf("Mismatch keys: %v != %v", want.(*AESMasterKey).key(), got.(*AESMasterKey).key()) + } + if _, err := ReadAESMasterKey([]byte("bar"), keyFile); err == nil { + t.Errorf("ReadMasterKey('bar') should have failed, but didn't") + } + }) + + t.Run("AES256WithTPMAESHMAC", func(t *testing.T) { + mk, err := CreateAESMasterKey(WithTPM(tpm), WithAlgo(AES256WithTPMAESHMAC)) + if err != nil { + t.Fatalf("CreateMasterKey: %v", err) + } + defer mk.Wipe() + if err := mk.Save(passphrase, keyFile); err != nil { + t.Fatalf("mk.Save: %v", err) + } + + mk2, err := ReadAESMasterKey(passphrase, keyFile, WithTPM(tpm)) + if err != nil { + t.Fatalf("ReadMasterKey(%q): %v", passphrase, err) + } + defer mk2.Wipe() + const message = "Hello world!" + enc, err := mk.Encrypt([]byte(message)) + if err != nil { + t.Fatalf("mk.Encrypt: %v", err) + } + dec, err := mk2.Decrypt(enc) + if err != nil { + t.Fatalf("mk.Decrypt: %v", err) + } + if got, want := string(dec), message; got != want { + t.Errorf("Mismatch message: %q != %q", got, want) + } + if _, err := ReadAESMasterKey([]byte("bar"), keyFile); err == nil { + t.Errorf("ReadMasterKey('bar') should have failed, but didn't") + } + }) } func TestAESEncryptDecrypt(t *testing.T) { @@ -163,30 +197,38 @@ func TestTPMAESEncryptedKey(t *testing.T) { } defer tpm.Close() - mk, err := CreateAESMasterKey(WithTPM(tpm)) - if err != nil { - t.Fatalf("CreateMasterKey: %v", err) - } - defer mk.Wipe() + for _, alg := range []int{AES256WithTPMRSA2048, AES256WithTPMAESHMAC} { + name := "AES256WithTPMRSA2048" + if alg == AES256WithTPMAESHMAC { + name = "AES256WithTPMAESHMAC" + } + t.Run(name, func(t *testing.T) { + mk, err := CreateAESMasterKey(WithTPM(tpm), WithAlgo(alg)) + if err != nil { + t.Fatalf("CreateMasterKey: %v", err) + } + defer mk.Wipe() - ek, err := mk.NewKey() - if err != nil { - t.Fatalf("mk.NewKey: %v", err) - } - defer ek.Wipe() + ek, err := mk.NewKey() + if err != nil { + t.Fatalf("mk.NewKey: %v", err) + } + defer ek.Wipe() - var buf bytes.Buffer - if err := ek.WriteEncryptedKey(&buf); err != nil { - t.Fatalf("ek.WriteEncryptedKey: %v", err) - } + var buf bytes.Buffer + if err := ek.WriteEncryptedKey(&buf); err != nil { + t.Fatalf("ek.WriteEncryptedKey: %v", err) + } - ek2, err := mk.ReadEncryptedKey(&buf) - if err != nil { - t.Fatalf("mk.ReadEncryptedKey: %v", err) - } - defer ek2.Wipe() - if want, got := ek.(*AESKey).key(), ek2.(*AESKey).key(); !reflect.DeepEqual(want, got) { - t.Errorf("Unexpected key. Want %+v, got %+v", want, got) + ek2, err := mk.ReadEncryptedKey(&buf) + if err != nil { + t.Fatalf("mk.ReadEncryptedKey: %v", err) + } + defer ek2.Wipe() + if want, got := ek.(*AESKey).key(), ek2.(*AESKey).key(); !reflect.DeepEqual(want, got) { + t.Errorf("Unexpected key. Want %+v, got %+v", want, got) + } + }) } } diff --git a/crypto/crypto.go b/crypto/crypto.go index 89a5feb..29c9e8a 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -39,6 +39,7 @@ const ( AES256 int = iota // AES256-GCM, AES256-CBC+HMAC-SHA256, PBKDF2. Chacha20Poly1305 // Chacha20Poly1305, Argon2. AES256WithTPMRSA2048 // Like AES256, with RSA2048 masterkey on TPM. + AES256WithTPMAESHMAC // Like AES256, with AES256+HMAC256 on TPM. DefaultAlgo = AES256 PickFastest = -1 @@ -142,7 +143,7 @@ func CreateMasterKey(opts ...Option) (MasterKey, error) { } } switch alg { - case AES256, AES256WithTPMRSA2048: + case AES256, AES256WithTPMRSA2048, AES256WithTPMAESHMAC: return CreateAESMasterKey(opts...) case Chacha20Poly1305: return CreateChacha20Poly1305MasterKey(opts...) diff --git a/go.mod b/go.mod index f0e66bb..05d6f2d 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,14 @@ go 1.24.0 toolchain go1.24.2 require ( - github.com/c2FmZQ/tpm v0.4.3 - github.com/google/go-tpm-tools v0.4.5 - golang.org/x/crypto v0.47.0 + github.com/c2FmZQ/tpm v0.5.0 + github.com/google/go-tpm-tools v0.4.7 + golang.org/x/crypto v0.48.0 ) require ( github.com/google/go-tpm v0.9.8 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect + golang.org/x/net v0.50.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect ) diff --git a/go.sum b/go.sum index bf33843..2b1de43 100644 --- a/go.sum +++ b/go.sum @@ -1,46 +1,28 @@ -github.com/c2FmZQ/tpm v0.4.1 h1:CTEEsdcpEoymUeBj4RIkoImx3+DVSCWqTCDtc5IqFyE= -github.com/c2FmZQ/tpm v0.4.1/go.mod h1:ESnZpMOfIHRkZuLajQGyGEFFHT3bt5YD5fo8XTd6Fg0= -github.com/c2FmZQ/tpm v0.4.3 h1:b5jjlqVyf5rdU0z0uohi5QylE6hb6vxryWGr3b3qCos= -github.com/c2FmZQ/tpm v0.4.3/go.mod h1:WOLrMYIX1ueasQqAdWcBjCwAJ+blrHEUxUcT1K0w360= +github.com/c2FmZQ/tpm v0.5.0 h1:b0YNCbiwnmUvIQQ7MiQfr1v7gz4h339/KusOGIrDLz8= +github.com/c2FmZQ/tpm v0.5.0/go.mod h1:R0HVAfw+Q//s64EwvyPB8UDMLsOD8OEcffkYYTbddQE= github.com/google/go-configfs-tsm v0.3.3-0.20240919001351-b4b5b84fdcbc h1:SG12DWUUM5igxm+//YX5Yq4vhdoRnOG9HkCodkOn+YU= github.com/google/go-configfs-tsm v0.3.3-0.20240919001351-b4b5b84fdcbc/go.mod h1:EL1GTDFMb5PZQWDviGfZV9n87WeGTR/JUg13RfwkgRo= -github.com/google/go-sev-guest v0.12.1 h1:H4rFYnPIn8HtqEsNTmh56Zxcf9BI9n48ZSYCnpYLYvc= -github.com/google/go-sev-guest v0.12.1/go.mod h1:SK9vW+uyfuzYdVN0m8BShL3OQCtXZe/JPF7ZkpD3760= +github.com/google/go-sev-guest v0.14.0 h1:dCb4F3YrHTtrDX3cYIPTifEDz7XagZmXQioxRBW4wOo= +github.com/google/go-sev-guest v0.14.0/go.mod h1:SK9vW+uyfuzYdVN0m8BShL3OQCtXZe/JPF7ZkpD3760= github.com/google/go-tdx-guest v0.3.2-0.20241009005452-097ee70d0843 h1:+MoPobRN9HrDhGyn6HnF5NYo4uMBKaiFqAtf/D/OB4A= github.com/google/go-tdx-guest v0.3.2-0.20241009005452-097ee70d0843/go.mod h1:g/n8sKITIT9xRivBUbizo34DTsUm2nN2uU3A662h09g= -github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU= -github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= -github.com/google/go-tpm-tools v0.4.5 h1:3fhthtyMDbIZFR5/0y1hvUoZ1Kf4i1eZ7C73R4Pvd+k= -github.com/google/go-tpm-tools v0.4.5/go.mod h1:ktjTNq8yZFD6TzdBFefUfen96rF3NpYwpSb2d8bc+Y8= +github.com/google/go-tpm-tools v0.4.7 h1:J3ycC8umYxM9A4eF73EofRZu4BxY0jjQnUnkhIBbvws= +github.com/google/go-tpm-tools v0.4.7/go.mod h1:gSyXTZHe3fgbzb6WEGd90QucmsnT1SRdlye82gH8QjQ= github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ= github.com/google/logger v1.1.1/go.mod h1:BkeJZ+1FhQ+/d087r4dzojEg1u2ZX+ZqG1jTUrLM+zQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=