generate and validate authorization message

This commit is contained in:
Roland Osborne 2022-01-18 20:46:45 -08:00
parent 12dfca0da3
commit 6412bd4df1
6 changed files with 87 additions and 17 deletions

View File

@ -4447,6 +4447,7 @@ components:
- keyType - keyType
- publicKey - publicKey
- signature - signature
- signatureType
properties: properties:
messageType: messageType:
type: string type: string
@ -4463,7 +4464,10 @@ components:
signature: signature:
type: string type: string
format: base64 encoding of message signature format: base64 encoding of message signature
signatureType:
type: string
enum: [PKCS1v15, PSS]
securitySchemes: securitySchemes:

View File

@ -36,13 +36,8 @@ func AddAccount(w http.ResponseWriter, r *http.Request) {
// compute key fingerprint // compute key fingerprint
msg := []byte(publicPem) msg := []byte(publicPem)
hash := sha256.New() hash := sha256.Sum256(msg)
if _, err = hash.Write(msg); err != nil { fingerprint := hex.EncodeToString(hash[:])
LogMsg("failed to fingerprint key")
w.WriteHeader(http.StatusInternalServerError)
return
}
fingerprint := hex.EncodeToString(hash.Sum(nil))
// create new account // create new account
account := store.Account{ account := store.Account{

View File

@ -1,13 +1,19 @@
package databag package databag
import ( import (
"crypto"
"crypto/rand"
"crypto/sha256"
"crypto/rsa"
"net/http" "net/http"
"encoding/json"
"encoding/base64"
"time" "time"
) )
func Authorize(w http.ResponseWriter, r *http.Request) { func Authorize(w http.ResponseWriter, r *http.Request) {
account, res := BearerAppToken(r); account, res := BearerAppToken(r, true);
if res != nil { if res != nil {
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return return
@ -19,13 +25,22 @@ func Authorize(w http.ResponseWriter, r *http.Request) {
// extract token from body // extract token from body
var token string var token string
if ParseRequest(r, w, &token) != nil { err := ParseRequest(r, w, &token)
if err != nil {
w.WriteHeader(http.StatusBadRequest); w.WriteHeader(http.StatusBadRequest);
return return
} }
// load details to sign data // 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 // generate message
auth := Authenticate{ auth := Authenticate{
@ -33,8 +48,27 @@ func Authorize(w http.ResponseWriter, r *http.Request) {
Token: token, Token: token,
Timestamp: time.Now().Unix(), 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") WriteResponse(w, msg)
w.WriteHeader(http.StatusOK)
} }

View File

@ -79,7 +79,7 @@ func BearerAccountToken(r *http.Request) (store.AccountToken, error) {
return accountToken, err return accountToken, err
} }
func BearerAppToken(r *http.Request) (store.Account, error) { func BearerAppToken(r *http.Request, detail bool) (store.Account, error) {
// parse bearer authentication // parse bearer authentication
auth := r.Header.Get("Authorization") auth := r.Header.Get("Authorization")
@ -87,8 +87,16 @@ func BearerAppToken(r *http.Request) (store.Account, error) {
// find token record // find token record
var app store.App var app store.App
err := store.DB.Preload("Account").Where("token = ?", token).First(&app).Error if detail {
return app.Account, err 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) { func BasicCredentials(r *http.Request) (string, []byte, error) {

View File

@ -132,6 +132,7 @@ type DataMessage struct {
KeyType string `json:"keyType"` KeyType string `json:"keyType"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
Signature string `json:"signature"` Signature string `json:"signature"`
SignatureType string `json:"signatureType"`
} }
type Dialogue struct { type Dialogue struct {

View File

@ -2,6 +2,13 @@ package databag
import ( import (
"testing" "testing"
"encoding/hex"
"encoding/json"
"encoding/base64"
"crypto/sha256"
"crypto/rsa"
"crypto"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -33,6 +40,27 @@ func TestAttachAccount(t *testing.T) {
var message DataMessage var message DataMessage
assert.NoError(t, ReadResponse(w, &message)) 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 // set profile
} }