Move JWK base64 decoding to JSON parsing step
This commit is contained in:
parent
360fe208a8
commit
e6cec49353
4 changed files with 45 additions and 75 deletions
|
@ -1,6 +1,9 @@
|
||||||
package libgm
|
package libgm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -333,9 +336,10 @@ func (c *Client) refreshAuthToken() error {
|
||||||
requestID := uuid.NewString()
|
requestID := uuid.NewString()
|
||||||
timestamp := time.Now().UnixMilli() * 1000
|
timestamp := time.Now().UnixMilli() * 1000
|
||||||
|
|
||||||
sig, sigErr := jwk.SignRequest(requestID, int64(timestamp))
|
signBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%d", requestID, timestamp)))
|
||||||
if sigErr != nil {
|
sig, err := ecdsa.SignASN1(rand.Reader, jwk.GetPrivateKey(), signBytes[:])
|
||||||
return sigErr
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
payloadMessage, messageErr := payload.RegisterRefresh(sig, requestID, int64(timestamp), c.authData.DevicePair.Browser, c.authData.TachyonAuthToken)
|
payloadMessage, messageErr := payload.RegisterRefresh(sig, requestID, int64(timestamp), c.authData.DevicePair.Browser, c.authData.TachyonAuthToken)
|
||||||
|
|
|
@ -4,84 +4,51 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type RawURLBytes []byte
|
||||||
|
|
||||||
|
func (rub RawURLBytes) MarshalJSON() ([]byte, error) {
|
||||||
|
out := make([]byte, 2+base64.RawURLEncoding.EncodedLen(len(rub)))
|
||||||
|
out[0] = '"'
|
||||||
|
base64.RawURLEncoding.Encode(out[1:], rub)
|
||||||
|
out[len(out)-1] = '"'
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rub *RawURLBytes) UnmarshalJSON(in []byte) error {
|
||||||
|
if len(in) < 2 || in[0] != '"' || in[len(in)-1] != '"' {
|
||||||
|
return fmt.Errorf("invalid value for RawURLBytes: not a JSON string")
|
||||||
|
}
|
||||||
|
*rub = make([]byte, base64.RawURLEncoding.DecodedLen(len(in)-2))
|
||||||
|
_, err := base64.RawURLEncoding.Decode(*rub, in[1:len(in)-1])
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
type JWK struct {
|
type JWK struct {
|
||||||
KeyType string `json:"kty"`
|
KeyType string `json:"kty"`
|
||||||
Curve string `json:"crv"`
|
Curve string `json:"crv"`
|
||||||
D string `json:"d"`
|
D RawURLBytes `json:"d"`
|
||||||
X string `json:"x"`
|
X RawURLBytes `json:"x"`
|
||||||
Y string `json:"y"`
|
Y RawURLBytes `json:"y"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *JWK) GetPrivateKey() (*ecdsa.PrivateKey, error) {
|
func (t *JWK) GetPrivateKey() *ecdsa.PrivateKey {
|
||||||
curve := elliptic.P256()
|
return &ecdsa.PrivateKey{
|
||||||
xBytes, err := base64.RawURLEncoding.DecodeString(t.X)
|
PublicKey: *t.GetPublicKey(),
|
||||||
if err != nil {
|
D: new(big.Int).SetBytes(t.D),
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
yBytes, err := base64.RawURLEncoding.DecodeString(t.Y)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dBytes, err := base64.RawURLEncoding.DecodeString(t.D)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv := &ecdsa.PrivateKey{
|
func (t *JWK) GetPublicKey() *ecdsa.PublicKey {
|
||||||
PublicKey: ecdsa.PublicKey{
|
return &ecdsa.PublicKey{
|
||||||
Curve: curve,
|
|
||||||
X: new(big.Int).SetBytes(xBytes),
|
|
||||||
Y: new(big.Int).SetBytes(yBytes),
|
|
||||||
},
|
|
||||||
D: new(big.Int).SetBytes(dBytes),
|
|
||||||
}
|
|
||||||
return priv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *JWK) GetPublicKey() (*ecdsa.PublicKey, error) {
|
|
||||||
xBytes, err := base64.RawURLEncoding.DecodeString(t.X)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
yBytes, err := base64.RawURLEncoding.DecodeString(t.Y)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
x := new(big.Int).SetBytes(xBytes)
|
|
||||||
y := new(big.Int).SetBytes(yBytes)
|
|
||||||
pubKey := &ecdsa.PublicKey{
|
|
||||||
Curve: elliptic.P256(),
|
Curve: elliptic.P256(),
|
||||||
X: x,
|
X: new(big.Int).SetBytes(t.X),
|
||||||
Y: y,
|
Y: new(big.Int).SetBytes(t.Y),
|
||||||
}
|
}
|
||||||
return pubKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *JWK) MarshalX509PublicKey() ([]byte, error) {
|
|
||||||
pubKey, err := t.GetPublicKey()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return x509.MarshalPKIXPublicKey(pubKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *JWK) SignRequest(requestID string, timestamp int64) ([]byte, error) {
|
|
||||||
signBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%d", requestID, timestamp)))
|
|
||||||
|
|
||||||
privKey, privErr := t.GetPrivateKey()
|
|
||||||
if privErr != nil {
|
|
||||||
return nil, privErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return ecdsa.SignASN1(rand.Reader, privKey, signBytes[:])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateECDSAKey generates a new ECDSA private key with P-256 curve
|
// GenerateECDSAKey generates a new ECDSA private key with P-256 curve
|
||||||
|
@ -93,8 +60,8 @@ func GenerateECDSAKey() (*JWK, error) {
|
||||||
return &JWK{
|
return &JWK{
|
||||||
KeyType: "EC",
|
KeyType: "EC",
|
||||||
Curve: "P-256",
|
Curve: "P-256",
|
||||||
D: base64.RawURLEncoding.EncodeToString(privKey.D.Bytes()),
|
D: privKey.D.Bytes(),
|
||||||
X: base64.RawURLEncoding.EncodeToString(privKey.X.Bytes()),
|
X: privKey.X.Bytes(),
|
||||||
Y: base64.RawURLEncoding.EncodeToString(privKey.Y.Bytes()),
|
Y: privKey.Y.Bytes(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,6 @@ type Pairer struct {
|
||||||
pairingKey []byte
|
pairingKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
refreshQrCodeTime is the interval to refresh the qr code in seconds, this is usually 20 seconds.
|
|
||||||
*/
|
|
||||||
func (c *Client) NewPairer(keyData *crypto.JWK, refreshQrCodeTime int) (*Pairer, error) {
|
func (c *Client) NewPairer(keyData *crypto.JWK, refreshQrCodeTime int) (*Pairer, error) {
|
||||||
if keyData == nil {
|
if keyData == nil {
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package payload
|
package payload
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
|
@ -9,7 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterPhoneRelay(jwk *crypto.JWK) ([]byte, *binary.AuthenticationContainer, error) {
|
func RegisterPhoneRelay(jwk *crypto.JWK) ([]byte, *binary.AuthenticationContainer, error) {
|
||||||
key, err := jwk.MarshalX509PublicKey()
|
key, err := x509.MarshalPKIXPublicKey(jwk.GetPublicKey())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue