// parseEncryptedFull parses a message in compact format. func parseEncryptedFull(input string) (*JsonWebEncryption, error) { var parsed rawJsonWebEncryption err := json.Unmarshal([]byte(input), &parsed) if err != nil { return nil, err } return parsed.sanitized() }
// parseSignedFull parses a message in full format. func parseSignedFull(input string) (*JsonWebSignature, error) { var parsed rawJsonWebSignature err := json.Unmarshal([]byte(input), &parsed) if err != nil { return nil, err } return parsed.sanitized() }
// UnmarshalJSON reads a key from its JSON representation. func (k *JsonWebKey) UnmarshalJSON(data []byte) (err error) { var raw rawJsonWebKey err = json.Unmarshal(data, &raw) if err != nil { return err } var key interface{} switch raw.Kty { case "EC": if raw.D != nil { key, err = raw.ecPrivateKey() } else { key, err = raw.ecPublicKey() } case "RSA": if raw.D != nil { key, err = raw.rsaPrivateKey() } else { key, err = raw.rsaPublicKey() } case "oct": key, err = raw.symmetricKey() default: err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty) } if err == nil { *k = JsonWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use} } k.Certificates = make([]*x509.Certificate, len(raw.X5c)) for i, cert := range raw.X5c { raw, err := base64.StdEncoding.DecodeString(cert) if err != nil { return err } k.Certificates[i], err = x509.ParseCertificate(raw) if err != nil { return err } } return }
func (b *byteBuffer) UnmarshalJSON(data []byte) error { var encoded string err := json.Unmarshal(data, &encoded) if err != nil { return err } if encoded == "" { return nil } decoded, err := base64URLDecode(encoded) if err != nil { return err } *b = *newBuffer(decoded) return nil }
// sanitized produces a cleaned-up JWE object from the raw JSON. func (parsed *rawJsonWebEncryption) sanitized() (*JsonWebEncryption, error) { obj := &JsonWebEncryption{ original: parsed, unprotected: parsed.Unprotected, } // Check that there is not a nonce in the unprotected headers if (parsed.Unprotected != nil && parsed.Unprotected.Nonce != "") || (parsed.Header != nil && parsed.Header.Nonce != "") { return nil, ErrUnprotectedNonce } if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected) if err != nil { return nil, fmt.Errorf("square/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64()) } } // Note: this must be called _after_ we parse the protected header, // otherwise fields from the protected header will not get picked up. obj.Header = obj.mergedHeaders(nil).sanitized() if len(parsed.Recipients) == 0 { obj.recipients = []recipientInfo{ recipientInfo{ header: parsed.Header, encryptedKey: parsed.EncryptedKey.bytes(), }, } } else { obj.recipients = make([]recipientInfo, len(parsed.Recipients)) for r := range parsed.Recipients { encryptedKey, err := base64URLDecode(parsed.Recipients[r].EncryptedKey) if err != nil { return nil, err } // Check that there is not a nonce in the unprotected header if parsed.Recipients[r].Header != nil && parsed.Recipients[r].Header.Nonce != "" { return nil, ErrUnprotectedNonce } obj.recipients[r].header = parsed.Recipients[r].Header obj.recipients[r].encryptedKey = encryptedKey } } for _, recipient := range obj.recipients { headers := obj.mergedHeaders(&recipient) if headers.Alg == "" || headers.Enc == "" { return nil, fmt.Errorf("square/go-jose: message is missing alg/enc headers") } } obj.iv = parsed.Iv.bytes() obj.ciphertext = parsed.Ciphertext.bytes() obj.tag = parsed.Tag.bytes() obj.aad = parsed.Aad.bytes() return obj, nil }
// sanitized produces a cleaned-up JWS object from the raw JSON. func (parsed *rawJsonWebSignature) sanitized() (*JsonWebSignature, error) { if parsed.Payload == nil { return nil, fmt.Errorf("square/go-jose: missing payload in JWS message") } obj := &JsonWebSignature{ payload: parsed.Payload.bytes(), Signatures: make([]Signature, len(parsed.Signatures)), } if len(parsed.Signatures) == 0 { // No signatures array, must be flattened serialization signature := Signature{} if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { signature.protected = &rawHeader{} err := json.Unmarshal(parsed.Protected.bytes(), signature.protected) if err != nil { return nil, err } } if parsed.Header != nil && parsed.Header.Nonce != "" { return nil, ErrUnprotectedNonce } signature.header = parsed.Header signature.Signature = parsed.Signature.bytes() // Make a fake "original" rawSignatureInfo to store the unprocessed // Protected header. This is necessary because the Protected header can // contain arbitrary fields not registered as part of the spec. See // https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-4 // If we unmarshal Protected into a rawHeader with its explicit list of fields, // we cannot marshal losslessly. So we have to keep around the original bytes. // This is used in computeAuthData, which will first attempt to use // the original bytes of a protected header, and fall back on marshaling the // header struct only if those bytes are not available. signature.original = &rawSignatureInfo{ Protected: parsed.Protected, Header: parsed.Header, Signature: parsed.Signature, } signature.Header = signature.mergedHeaders().sanitized() obj.Signatures = append(obj.Signatures, signature) } for i, sig := range parsed.Signatures { if sig.Protected != nil && len(sig.Protected.bytes()) > 0 { obj.Signatures[i].protected = &rawHeader{} err := json.Unmarshal(sig.Protected.bytes(), obj.Signatures[i].protected) if err != nil { return nil, err } } // Check that there is not a nonce in the unprotected header if sig.Header != nil && sig.Header.Nonce != "" { return nil, ErrUnprotectedNonce } obj.Signatures[i].Signature = sig.Signature.bytes() // Copy value of sig original := sig obj.Signatures[i].header = sig.Header obj.Signatures[i].original = &original obj.Signatures[i].Header = obj.Signatures[i].mergedHeaders().sanitized() } return obj, nil }