| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package restsigner |
| |
| import ( |
| "crypto/ecdsa" |
| "crypto/x509" |
| "encoding/base64" |
| "fmt" |
| "math/big" |
| |
| "golang.org/x/oauth2" |
| "golang.org/x/oauth2/google" |
| "v.io/v23/security" |
| signer "v.io/x/ref/services/internal/restsigner/v1" |
| ) |
| |
| func DecodePublicKey(k *signer.PublicKey) (*ecdsa.PublicKey, error) { |
| bytes, err := base64.URLEncoding.DecodeString(k.Base64) |
| if err != nil { |
| return nil, err |
| } |
| key, err := x509.ParsePKIXPublicKey(bytes) |
| if err != nil { |
| return nil, err |
| } |
| pub, ok := key.(*ecdsa.PublicKey) |
| if !ok { |
| return nil, fmt.Errorf("Not an ECDSA public key") |
| } |
| return pub, nil |
| } |
| |
| func DecodeSignature(sig *signer.VSignature) (r, s *big.Int, err error) { |
| r, s = new(big.Int), new(big.Int) |
| if _, ok := r.SetString(sig.R, 0); !ok { |
| return nil, nil, fmt.Errorf("unable to parse big.Int %s", sig.R) |
| } |
| if _, ok := s.SetString(sig.S, 0); !ok { |
| return nil, nil, fmt.Errorf("unable to parse big.Int %s", sig.S) |
| } |
| return |
| } |
| |
| func NewRestSigner() (security.Signer, error) { |
| client, err := signer.New(oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource(""))) |
| if err != nil { |
| return nil, err |
| } |
| jkey, err := client.PublicKey().Do() |
| if err != nil { |
| return nil, err |
| } |
| key, err := DecodePublicKey(jkey) |
| if err != nil { |
| return nil, err |
| } |
| sign := func(message []byte) (r, s *big.Int, err error) { |
| msgBase64 := base64.URLEncoding.EncodeToString(message) |
| jsig, err := client.Sign(msgBase64).Do() |
| if err != nil { |
| return nil, nil, err |
| } |
| return DecodeSignature(jsig) |
| } |
| return security.NewECDSASigner(key, sign), nil |
| } |