crypto: change ErrNotRSAPrivateKey to ErrNotRSAPublicKey
Fixes: #19
diff --git a/cover.html b/cover.html
deleted file mode 100644
index 316b917..0000000
--- a/cover.html
+++ /dev/null
@@ -1,268 +0,0 @@
-
-<!DOCTYPE html>
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <style>
- body {
- background: black;
- color: rgb(80, 80, 80);
- }
- body, pre, #legend span {
- font-family: Menlo, monospace;
- font-weight: bold;
- }
- #topbar {
- background: black;
- position: fixed;
- top: 0; left: 0; right: 0;
- height: 42px;
- border-bottom: 1px solid rgb(80, 80, 80);
- }
- #content {
- margin-top: 50px;
- }
- #nav, #legend {
- float: left;
- margin-left: 10px;
- }
- #legend {
- margin-top: 12px;
- }
- #nav {
- margin-top: 10px;
- }
- #legend span {
- margin: 0 5px;
- }
- .cov0 { color: rgb(192, 0, 0) }
-.cov1 { color: rgb(128, 128, 128) }
-.cov2 { color: rgb(116, 140, 131) }
-.cov3 { color: rgb(104, 152, 134) }
-.cov4 { color: rgb(92, 164, 137) }
-.cov5 { color: rgb(80, 176, 140) }
-.cov6 { color: rgb(68, 188, 143) }
-.cov7 { color: rgb(56, 200, 146) }
-.cov8 { color: rgb(44, 212, 149) }
-.cov9 { color: rgb(32, 224, 152) }
-.cov10 { color: rgb(20, 236, 155) }
-
- </style>
- </head>
- <body>
- <div id="topbar">
- <div id="nav">
- <select id="files">
-
- <option value="file0">github.com/SermoDigital/jose/base64.go (100.0%)</option>
-
- <option value="file1">github.com/SermoDigital/jose/header.go (58.1%)</option>
-
- </select>
- </div>
- <div id="legend">
- <span>not tracked</span>
-
- <span class="cov0">not covered</span>
- <span class="cov8">covered</span>
-
- </div>
- </div>
- <div id="content">
-
- <pre class="file" id="file0" >package jose
-
-import "encoding/base64"
-
-// Encoder is satisfied if the type can marshal itself into a valid
-// structure for a JWS.
-type Encoder interface {
- // Base64 implies T -> JSON -> RawURLEncodingBase64
- Base64() ([]byte, error)
-}
-
-// Base64Decode decodes a base64-encoded byte slice.
-func Base64Decode(b []byte) ([]byte, error) <span class="cov8" title="1">{
- buf := make([]byte, base64.RawURLEncoding.DecodedLen(len(b)))
- n, err := base64.RawURLEncoding.Decode(buf, b)
- return buf[:n], err
-}</span>
-
-// Base64Encode encodes a byte slice.
-func Base64Encode(b []byte) []byte <span class="cov8" title="1">{
- buf := make([]byte, base64.RawURLEncoding.EncodedLen(len(b)))
- base64.RawURLEncoding.Encode(buf, b)
- return buf
-}</span>
-
-// EncodeEscape base64-encodes a byte slice but escapes it for JSON.
-// It'll return the format: `"base64"`
-func EncodeEscape(b []byte) []byte <span class="cov8" title="1">{
- buf := make([]byte, base64.RawURLEncoding.EncodedLen(len(b))+2)
- buf[0] = '"'
- base64.RawURLEncoding.Encode(buf[1:], b)
- buf[len(buf)-1] = '"'
- return buf
-}</span>
-
-// DecodeEscaped decodes a base64-encoded byte slice straight from a JSON
-// structure. It assumes it's in the format: `"base64"`, but can handle
-// cases where it's not.
-func DecodeEscaped(b []byte) ([]byte, error) <span class="cov8" title="1">{
- if len(b) > 1 && b[0] == '"' && b[len(b)-1] == '"' </span><span class="cov8" title="1">{
- b = b[1 : len(b)-1]
- }</span>
- <span class="cov8" title="1">return Base64Decode(b)</span>
-}
-</pre>
-
- <pre class="file" id="file1" style="display: none">package jose
-
-import "encoding/json"
-
-// Header implements a JOSE Header with the addition of some helper
-// methods, similar to net/url.Values.
-type Header map[string]interface{}
-
-// Get retrieves the value corresponding with key from the Header.
-func (h Header) Get(key string) interface{} <span class="cov8" title="1">{
- if h == nil </span><span class="cov8" title="1">{
- return nil
- }</span>
- <span class="cov8" title="1">return h[key]</span>
-}
-
-// Set sets Claims[key] = val. It'll overwrite without warning.
-func (h Header) Set(key string, val interface{}) <span class="cov8" title="1">{
- h[key] = val
-}</span>
-
-// Del removes the value that corresponds with key from the Header.
-func (h Header) Del(key string) <span class="cov8" title="1">{
- delete(h, key)
-}</span>
-
-// Has returns true if a value for the given key exists inside the Header.
-func (h Header) Has(key string) bool <span class="cov8" title="1">{
- _, ok := h[key]
- return ok
-}</span>
-
-// MarshalJSON implements json.Marshaler for Header.
-func (h Header) MarshalJSON() ([]byte, error) <span class="cov8" title="1">{
- if h == nil || len(h) == 0 </span><span class="cov0" title="0">{
- return nil, nil
- }</span>
- <span class="cov8" title="1">b, err := json.Marshal(map[string]interface{}(h))
- if err != nil </span><span class="cov0" title="0">{
- return nil, err
- }</span>
- <span class="cov8" title="1">return EncodeEscape(b), nil</span>
-}
-
-// Base64 implements the Encoder interface.
-func (h Header) Base64() ([]byte, error) <span class="cov0" title="0">{
- return h.MarshalJSON()
-}</span>
-
-// UnmarshalJSON implements json.Unmarshaler for Header.
-func (h *Header) UnmarshalJSON(b []byte) error <span class="cov8" title="1">{
- if b == nil </span><span class="cov0" title="0">{
- return nil
- }</span>
-
- <span class="cov8" title="1">b, err := DecodeEscaped(b)
- if err != nil </span><span class="cov0" title="0">{
- return err
- }</span>
-
- // Since json.Unmarshal calls UnmarshalJSON,
- // calling json.Unmarshal on *p would be infinitely recursive
- // A temp variable is needed because &map[string]interface{}(*p) is
- // invalid Go.
-
- <span class="cov8" title="1">tmp := map[string]interface{}(*h)
- if err = json.Unmarshal(b, &tmp); err != nil </span><span class="cov0" title="0">{
- return err
- }</span>
- <span class="cov8" title="1">*h = Header(tmp)
- return nil</span>
-}
-
-// Protected Headers are base64-encoded after they're marshaled into
-// JSON.
-type Protected Header
-
-// Get retrieves the value corresponding with key from the Protected Header.
-func (p Protected) Get(key string) interface{} <span class="cov0" title="0">{
- if p == nil </span><span class="cov0" title="0">{
- return nil
- }</span>
- <span class="cov0" title="0">return p[key]</span>
-}
-
-// Set sets Protected[key] = val. It'll overwrite without warning.
-func (p Protected) Set(key string, val interface{}) <span class="cov0" title="0">{
- p[key] = val
-}</span>
-
-// Del removes the value that corresponds with key from the Protected Header.
-func (p Protected) Del(key string) <span class="cov0" title="0">{
- delete(p, key)
-}</span>
-
-// Has returns true if a value for the given key exists inside the Protected
-// Header.
-func (p Protected) Has(key string) bool <span class="cov0" title="0">{
- _, ok := p[key]
- return ok
-}</span>
-
-// MarshalJSON implements json.Marshaler for Protected.
-func (p Protected) MarshalJSON() ([]byte, error) <span class="cov8" title="1">{
- b, err := json.Marshal(map[string]interface{}(p))
- if err != nil </span><span class="cov0" title="0">{
- return nil, err
- }</span>
- <span class="cov8" title="1">return EncodeEscape(b), nil</span>
-}
-
-// Base64 implements the Encoder interface.
-func (p Protected) Base64() ([]byte, error) <span class="cov0" title="0">{
- b, err := json.Marshal(map[string]interface{}(p))
- if err != nil </span><span class="cov0" title="0">{
- return nil, err
- }</span>
- <span class="cov0" title="0">return Base64Encode(b), nil</span>
-}
-
-// UnmarshalJSON implements json.Unmarshaler for Protected.
-func (p *Protected) UnmarshalJSON(b []byte) error <span class="cov8" title="1">{
- var h Header
- h.UnmarshalJSON(b)
- *p = Protected(h)
- return nil
-}</span>
-
-var (
- _ json.Marshaler = (Protected)(nil)
- _ json.Unmarshaler = (*Protected)(nil)
-)
-</pre>
-
- </div>
- </body>
- <script>
- (function() {
- var files = document.getElementById('files');
- var visible = document.getElementById('file0');
- files.addEventListener('change', onChange, false);
- function onChange() {
- visible.style.display = 'none';
- visible = document.getElementById(files.value);
- visible.style.display = 'block';
- window.scrollTo(0, 0);
- }
- })();
- </script>
-</html>
diff --git a/crypto/rsa_utils.go b/crypto/rsa_utils.go
index 350c394..43aeff3 100644
--- a/crypto/rsa_utils.go
+++ b/crypto/rsa_utils.go
@@ -9,8 +9,9 @@
// Errors specific to rsa_utils.
var (
- ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key")
- ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key")
+ ErrKeyMustBePEMEncoded = errors.New("invalid key: Key must be PEM encoded PKCS1 or PKCS8 private key")
+ ErrNotRSAPrivateKey = errors.New("key is not a valid RSA private key")
+ ErrNotRSAPublicKey = errors.New("key is not a valid RSA public key")
)
// ParseRSAPrivateKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 private key.
@@ -62,7 +63,7 @@
var pkey *rsa.PublicKey
var ok bool
if pkey, ok = parsedKey.(*rsa.PublicKey); !ok {
- return nil, ErrNotRSAPrivateKey
+ return nil, ErrNotRSAPublicKey
}
return pkey, nil
diff --git a/jws/jws_validate.go b/jws/jws_validate.go
index 1948880..d064113 100644
--- a/jws/jws_validate.go
+++ b/jws/jws_validate.go
@@ -27,40 +27,34 @@
return j.VerifyMulti(keys, methods, o)
}
-// IsMultiError returns true if the given error is type MultiError.
+// IsMultiError returns true if the given error is type *MultiError.
func IsMultiError(err error) bool {
- _, ok := err.(MultiError)
+ _, ok := err.(*MultiError)
return ok
}
// MultiError is a slice of errors.
type MultiError []error
-func (m MultiError) sanityCheck() error {
- if m == nil {
- return nil
- }
- return m
-}
-
// Errors implements the error interface.
-func (m MultiError) Error() string {
- s, n := "", 0
- for _, e := range m {
- if e != nil {
+func (m *MultiError) Error() string {
+ var s string
+ var n int
+ for _, err := range *m {
+ if err != nil {
if n == 0 {
- s = e.Error()
+ s = err.Error()
}
n++
}
}
switch n {
case 0:
- return "(0 errors)"
+ return ""
case 1:
return s
case 2:
- return s + " (and 1 other error)"
+ return s + " and 1 other error"
}
return fmt.Sprintf("%s (and %d other errors)", s, n-1)
}
@@ -101,7 +95,7 @@
var o2 SigningOpts
if o == nil {
- o = &SigningOpts{}
+ o = new(SigningOpts)
}
var m MultiError
@@ -112,15 +106,20 @@
} else {
o2.Inc()
if o.Needs(i) {
+ o.ptr++
o2.Append(i)
}
}
}
- if err := o.Validate(&o2); err != nil {
- return err
+ err := o.Validate(&o2)
+ if err != nil {
+ m = append(m, err)
}
- return m.sanityCheck()
+ if len(m) == 0 {
+ return nil
+ }
+ return &m
}
// SigningOpts is a struct which holds options for validating
@@ -148,30 +147,24 @@
_ struct{}
}
-// Append appends x to s's Indices member.
+// Append appends x to s' Indices member.
func (s *SigningOpts) Append(x int) {
s.Indices = append(s.Indices, x)
}
-// Needs returns true if x resides inside s's Indices member
-// for the given index. If true, it increments s's internal
-// index. It's used to match two SigningOpts Indices members.
+// Needs returns true if x resides inside s' Indices member
+// for the given index. It's used to match two SigningOpts Indices members.
func (s *SigningOpts) Needs(x int) bool {
- if s.ptr < len(s.Indices) &&
- s.Indices[s.ptr] == x {
- s.ptr++
- return true
- }
- return false
+ return s.ptr < len(s.Indices) && s.Indices[s.ptr] == x
}
-// Inc increments s's Number member by one.
+// Inc increments s' Number member by one.
func (s *SigningOpts) Inc() { s.Number++ }
// Validate returns any errors found while validating the
-// provided SigningOpts. The receiver validates the parameter `have`.
+// provided SigningOpts. The receiver validates |have|.
// It'll return an error if the passed SigningOpts' Number member is less
-// than s's or if the passed SigningOpts' Indices slice isn't equal to s's.
+// than s' or if the passed SigningOpts' Indices slice isn't equal to s'.
func (s *SigningOpts) Validate(have *SigningOpts) error {
if have.Number < s.Number ||
(s.Indices != nil &&
@@ -182,10 +175,7 @@
}
func eq(a, b []int) bool {
- if a == nil && b == nil {
- return true
- }
- if a == nil || b == nil || len(a) != len(b) {
+ if len(a) != len(b) {
return false
}
for i := range a {
diff --git a/jws/jwt.go b/jws/jwt.go
index f98edf1..29b75b8 100644
--- a/jws/jwt.go
+++ b/jws/jwt.go
@@ -10,7 +10,10 @@
// NewJWT creates a new JWT with the given claims.
func NewJWT(claims Claims, method crypto.SigningMethod) jwt.JWT {
- j := New(claims, method).(*jws)
+ j, ok := New(claims, method).(*jws)
+ if !ok {
+ panic("jws.NewJWT: runtime panic: New(...).(*jws) != true")
+ }
j.sb[0].protected.Set("typ", "JWT")
j.isJWT = true
return j
@@ -98,8 +101,7 @@
}
}
-// NewValidator returns a pointer to a jwt.Validator structure containing
-// the info to be used in the validation of a JWT.
+// NewValidator returns a jwt.Validator.
func NewValidator(c Claims, exp, nbf time.Duration, fn func(Claims) error) *jwt.Validator {
return &jwt.Validator{
Expected: jwt.Claims(c),