github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/creds/creds.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package creds 16 17 import ( 18 "context" 19 "crypto/sha512" 20 "encoding/base32" 21 "errors" 22 "time" 23 24 "golang.org/x/crypto/ed25519" 25 "gopkg.in/square/go-jose.v2" 26 "gopkg.in/square/go-jose.v2/jwt" 27 28 "github.com/dolthub/dolt/go/libraries/utils/set" 29 "github.com/dolthub/dolt/go/store/util/datetime" 30 ) 31 32 const ( 33 pubKeySize = 32 34 privKeySize = 64 35 ) 36 37 const ( 38 B32CharEncoding = "0123456789abcdefghijklmnopqrstuv" 39 40 B32EncodedPubKeyLen = 52 41 B32EncodedKeyIdLen = 45 42 43 JWTKIDHeader = "kid" 44 JWTAlgHeader = "alg" 45 ) 46 47 var B32CredsByteSet = set.NewByteSet([]byte(B32CharEncoding)) 48 var B32CredsEncoding = base32.NewEncoding(B32CharEncoding).WithPadding(base32.NoPadding) 49 var EmptyCreds = DoltCreds{} 50 51 var ErrBadB32CredsEncoding = errors.New("bad base32 credentials encoding") 52 var ErrCredsNotFound = errors.New("credentials not found") 53 54 type DoltCreds struct { 55 PubKey []byte 56 PrivKey []byte 57 KeyID []byte 58 } 59 60 func PubKeyStrToKIDStr(pub string) (string, error) { 61 data, err := B32CredsEncoding.DecodeString(pub) 62 63 if err != nil { 64 return "", err 65 } 66 67 return PubKeyToKIDStr(data), nil 68 } 69 70 func PubKeyToKID(pub []byte) []byte { 71 kidBytes := sha512.Sum512_224(pub) 72 return kidBytes[:] 73 } 74 75 func PubKeyToKIDStr(pub []byte) string { 76 kidBytes := PubKeyToKID(pub) 77 kid := B32CredsEncoding.EncodeToString(kidBytes) 78 return kid 79 } 80 81 func GenerateCredentials() (DoltCreds, error) { 82 pub, priv, err := ed25519.GenerateKey(nil) 83 84 if err == nil { 85 kid := PubKeyToKID(pub) 86 return DoltCreds{pub, priv, kid}, nil 87 } 88 89 return DoltCreds{}, err 90 } 91 92 func (dc DoltCreds) HasPrivKey() bool { 93 return len(dc.PrivKey) > 0 94 } 95 96 func (dc DoltCreds) IsPrivKeyValid() bool { 97 return len(dc.PrivKey) == privKeySize 98 } 99 100 func (dc DoltCreds) IsPubKeyValid() bool { 101 return len(dc.PubKey) == pubKeySize 102 } 103 104 func (dc DoltCreds) PubKeyBase32Str() string { 105 return B32CredsEncoding.EncodeToString(dc.PubKey) 106 } 107 108 func (dc DoltCreds) PrivKeyBase32Str() string { 109 return B32CredsEncoding.EncodeToString(dc.PubKey) 110 } 111 112 func (dc DoltCreds) KeyIDBase32Str() string { 113 return B32CredsEncoding.EncodeToString(dc.KeyID) 114 } 115 116 func (dc DoltCreds) Sign(data []byte) []byte { 117 return ed25519.Sign(dc.PrivKey, data) 118 } 119 120 func (dc DoltCreds) toBearerToken() (string, error) { 121 b32KIDStr := dc.KeyIDBase32Str() 122 key := jose.SigningKey{Algorithm: jose.EdDSA, Key: ed25519.PrivateKey(dc.PrivKey)} 123 opts := &jose.SignerOptions{ExtraHeaders: map[jose.HeaderKey]interface{}{ 124 JWTKIDHeader: b32KIDStr, 125 }} 126 127 signer, err := jose.NewSigner(key, opts) 128 129 if err != nil { 130 return "", err 131 } 132 133 // Shouldn't be hard coded 134 jwtBuilder := jwt.Signed(signer) 135 jwtBuilder = jwtBuilder.Claims(jwt.Claims{ 136 Audience: []string{"dolthub-remote-api.liquidata.co"}, 137 Issuer: "dolt-client.liquidata.co", 138 Subject: "doltClientCredentials/" + b32KIDStr, 139 Expiry: jwt.NewNumericDate(datetime.Now().Add(30 * time.Second)), 140 }) 141 142 return jwtBuilder.CompactSerialize() 143 } 144 145 func (dc DoltCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 146 t, err := dc.toBearerToken() 147 148 if err != nil { 149 return nil, err 150 } 151 152 return map[string]string{ 153 "authorization": "Bearer " + t, 154 }, nil 155 } 156 157 func (dc DoltCreds) RequireTransportSecurity() bool { 158 return false 159 }