129 lines
2.3 KiB
Go
129 lines
2.3 KiB
Go
package jose
|
|
|
|
import (
|
|
"crypto/elliptic"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"errors"
|
|
"math/big"
|
|
"strings"
|
|
)
|
|
|
|
// Base64 functions
|
|
|
|
// NOTE: These are replicated in boulder/core. However, that module
|
|
// also needs to refer to JWKs, so removing the duplication would
|
|
// cause a dependency loop. We are hoping to eliminate this code
|
|
// soon, in favor of th Square JOSE library, so we are tolerating
|
|
// the duplication for now.
|
|
|
|
func pad(x string) string {
|
|
switch len(x) % 4 {
|
|
case 2:
|
|
return x + "=="
|
|
case 3:
|
|
return x + "="
|
|
}
|
|
return x
|
|
}
|
|
|
|
func unpad(x string) string {
|
|
return strings.Replace(x, "=", "", -1)
|
|
}
|
|
|
|
func B64enc(x []byte) string {
|
|
return unpad(base64.URLEncoding.EncodeToString(x))
|
|
}
|
|
|
|
func B64dec(x string) ([]byte, error) {
|
|
return base64.URLEncoding.DecodeString(pad(x))
|
|
}
|
|
|
|
// Buffers that know how to do b64 and bigint
|
|
type JsonBuffer json.RawMessage
|
|
|
|
func (jb JsonBuffer) MarshalJSON() ([]byte, error) {
|
|
str := B64enc(jb)
|
|
return json.Marshal(str)
|
|
}
|
|
|
|
func (jb *JsonBuffer) UnmarshalJSON(data []byte) error {
|
|
var str string
|
|
err := json.Unmarshal(data, &str)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*jb, err = B64dec(str)
|
|
return err
|
|
}
|
|
|
|
func (jb JsonBuffer) ToBigInt() *big.Int {
|
|
ret := big.NewInt(0)
|
|
ret.SetBytes(jb)
|
|
return ret
|
|
}
|
|
|
|
func (jb JsonBuffer) ToInt() int {
|
|
return int(jb.ToBigInt().Int64())
|
|
}
|
|
|
|
// Utils
|
|
|
|
func bigint2base64(x *big.Int) string {
|
|
return B64enc(x.Bytes())
|
|
}
|
|
|
|
func int2base64(x int) string {
|
|
b := big.NewInt(int64(x))
|
|
return bigint2base64(b)
|
|
}
|
|
|
|
func base642bigint(x string) (*big.Int, error) {
|
|
data, err := B64dec(x)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bn := big.NewInt(0)
|
|
bn.SetBytes(data)
|
|
return bn, nil
|
|
}
|
|
|
|
func base642int(x string) (int, error) {
|
|
bn, err := base642bigint(x)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return int(bn.Int64()), nil
|
|
}
|
|
|
|
func name2curve(name string) (elliptic.Curve, error) {
|
|
switch name {
|
|
case "P-256":
|
|
return elliptic.P256(), nil
|
|
case "P-384":
|
|
return elliptic.P384(), nil
|
|
case "P-521":
|
|
return elliptic.P521(), nil
|
|
}
|
|
|
|
var dummy elliptic.Curve
|
|
return dummy, errors.New("Unknown elliptic curve " + name)
|
|
}
|
|
|
|
func curve2name(curve elliptic.Curve) (string, error) {
|
|
// XXX DANGER ASSUMES ONE CURVE PER BIT SIZE
|
|
switch curve.Params().BitSize {
|
|
case 256:
|
|
return "P-256", nil
|
|
case 384:
|
|
return "P-384", nil
|
|
case 521:
|
|
return "P-521", nil
|
|
}
|
|
|
|
return "", errors.New("Unknown elliptic curve")
|
|
}
|