From 6412bd4df16ab4699557c1b3a70e3e1f5f3cf6ea Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Tue, 18 Jan 2022 20:46:45 -0800 Subject: [PATCH] generate and validate authorization message --- doc/api.oa3 | 6 +++- net/server/internal/api_addAccount.go | 9 ++--- net/server/internal/api_authorize.go | 46 +++++++++++++++++++++---- net/server/internal/auth.go | 14 ++++++-- net/server/internal/models.go | 1 + net/server/internal/ucAttachApp_test.go | 28 +++++++++++++++ 6 files changed, 87 insertions(+), 17 deletions(-) diff --git a/doc/api.oa3 b/doc/api.oa3 index 6c7bcaa1..90b7ff73 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -4447,6 +4447,7 @@ components: - keyType - publicKey - signature + - signatureType properties: messageType: type: string @@ -4463,7 +4464,10 @@ components: signature: type: string format: base64 encoding of message signature - + signatureType: + type: string + enum: [PKCS1v15, PSS] + securitySchemes: diff --git a/net/server/internal/api_addAccount.go b/net/server/internal/api_addAccount.go index 24b8002b..6d7b6653 100644 --- a/net/server/internal/api_addAccount.go +++ b/net/server/internal/api_addAccount.go @@ -36,13 +36,8 @@ func AddAccount(w http.ResponseWriter, r *http.Request) { // compute key fingerprint msg := []byte(publicPem) - hash := sha256.New() - if _, err = hash.Write(msg); err != nil { - LogMsg("failed to fingerprint key") - w.WriteHeader(http.StatusInternalServerError) - return - } - fingerprint := hex.EncodeToString(hash.Sum(nil)) + hash := sha256.Sum256(msg) + fingerprint := hex.EncodeToString(hash[:]) // create new account account := store.Account{ diff --git a/net/server/internal/api_authorize.go b/net/server/internal/api_authorize.go index 3a06beca..af47e992 100644 --- a/net/server/internal/api_authorize.go +++ b/net/server/internal/api_authorize.go @@ -1,13 +1,19 @@ package databag import ( + "crypto" + "crypto/rand" + "crypto/sha256" + "crypto/rsa" "net/http" + "encoding/json" + "encoding/base64" "time" ) func Authorize(w http.ResponseWriter, r *http.Request) { - account, res := BearerAppToken(r); + account, res := BearerAppToken(r, true); if res != nil { w.WriteHeader(http.StatusUnauthorized) return @@ -19,13 +25,22 @@ func Authorize(w http.ResponseWriter, r *http.Request) { // extract token from body var token string - if ParseRequest(r, w, &token) != nil { + err := ParseRequest(r, w, &token) + if err != nil { w.WriteHeader(http.StatusBadRequest); return } // load details to sign data - + if account.AccountDetail.KeyType != "RSA4096" { + w.WriteHeader(http.StatusServiceUnavailable) + return + } + privateKey, res := ParseRsaPrivateKeyFromPemStr(account.AccountDetail.PrivateKey); + if res != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } // generate message auth := Authenticate{ @@ -33,8 +48,27 @@ func Authorize(w http.ResponseWriter, r *http.Request) { Token: token, Timestamp: time.Now().Unix(), } - PrintMsg(auth); + var data []byte + data, err = json.Marshal(auth); + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + hash := sha256.Sum256(data); + var signature []byte + signature, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:]) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + msg := DataMessage{ + MessageType: "authenticate", + Message: base64.StdEncoding.EncodeToString([]byte(data)), + KeyType: account.AccountDetail.KeyType, + PublicKey: base64.StdEncoding.EncodeToString([]byte(account.AccountDetail.PublicKey)), + Signature: base64.StdEncoding.EncodeToString(signature), + SignatureType: "PKCS1v15", + } - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) + WriteResponse(w, msg) } diff --git a/net/server/internal/auth.go b/net/server/internal/auth.go index 9c784d7b..e08334d9 100644 --- a/net/server/internal/auth.go +++ b/net/server/internal/auth.go @@ -79,7 +79,7 @@ func BearerAccountToken(r *http.Request) (store.AccountToken, error) { return accountToken, err } -func BearerAppToken(r *http.Request) (store.Account, error) { +func BearerAppToken(r *http.Request, detail bool) (store.Account, error) { // parse bearer authentication auth := r.Header.Get("Authorization") @@ -87,8 +87,16 @@ func BearerAppToken(r *http.Request) (store.Account, error) { // find token record var app store.App - err := store.DB.Preload("Account").Where("token = ?", token).First(&app).Error - return app.Account, err + if detail { + if store.DB.Preload("Account.AccountDetail").Where("token = ?", token).First(&app).Error != nil { + return app.Account, errors.New("failed to load account"); + } + } else { + if store.DB.Preload("Account").Where("token = ?", token).First(&app).Error != nil { + return app.Account, errors.New("failed to load account"); + } + } + return app.Account, nil } func BasicCredentials(r *http.Request) (string, []byte, error) { diff --git a/net/server/internal/models.go b/net/server/internal/models.go index 2d8d110b..2c182e9d 100644 --- a/net/server/internal/models.go +++ b/net/server/internal/models.go @@ -132,6 +132,7 @@ type DataMessage struct { KeyType string `json:"keyType"` PublicKey string `json:"publicKey"` Signature string `json:"signature"` + SignatureType string `json:"signatureType"` } type Dialogue struct { diff --git a/net/server/internal/ucAttachApp_test.go b/net/server/internal/ucAttachApp_test.go index 14c0832b..7646d109 100644 --- a/net/server/internal/ucAttachApp_test.go +++ b/net/server/internal/ucAttachApp_test.go @@ -2,6 +2,13 @@ package databag import ( "testing" + "encoding/hex" + "encoding/json" + "encoding/base64" + "crypto/sha256" + "crypto/rsa" + "crypto" + "time" "github.com/stretchr/testify/assert" ) @@ -33,6 +40,27 @@ func TestAttachAccount(t *testing.T) { var message DataMessage assert.NoError(t, ReadResponse(w, &message)) + // validate message + assert.Equal(t, "RSA4096", message.KeyType) + assert.Equal(t, "PKCS1v15", message.SignatureType) + var data []byte + var hash [32]byte + data, _ = base64.StdEncoding.DecodeString(message.PublicKey) + hash = sha256.Sum256(data) + guid := hex.EncodeToString(hash[:]) + publicKey, _ := ParseRsaPublicKeyFromPemStr(string(data)) + signature, _ := base64.StdEncoding.DecodeString(message.Signature) + data, _ = base64.StdEncoding.DecodeString(message.Message) + hash = sha256.Sum256(data) + assert.NoError(t, rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash[:], signature)) + var auth Authenticate + assert.NoError(t, json.Unmarshal(data,&auth)) + assert.Equal(t, "aabbccdd", auth.Token) + assert.Equal(t, guid, auth.Guid) + cur := time.Now().Unix() + assert.GreaterOrEqual(t, cur, auth.Timestamp) + assert.Less(t, cur - 60, auth.Timestamp) + // set profile }