func encrypt(payload []byte, jwtHeader map[string]interface{}, key interface{}) (token string, err error) { var ok bool var keyMgmtAlg JwaAlgorithm var encAlg JweEncryption alg := jwtHeader["alg"].(string) enc := jwtHeader["enc"].(string) if keyMgmtAlg, ok = jwaAlgorithms[alg]; !ok { return "", errors.New(fmt.Sprintf("jwt.encrypt(): Unknown key management algorithm '%v'", alg)) } if encAlg, ok = jweEncryptors[enc]; !ok { return "", errors.New(fmt.Sprintf("jwt.encrypt(): Unknown encryption algorithm '%v'", enc)) } var cek, encryptedCek, header, iv, cipherText, authTag []byte if cek, encryptedCek, err = keyMgmtAlg.WrapNewKey(encAlg.KeySizeBits(), key, jwtHeader); err != nil { return "", err } if header, err = json.Marshal(jwtHeader); err != nil { return "", err } if iv, cipherText, authTag, err = encAlg.Encrypt([]byte(compact.Serialize(header)), payload, cek); err != nil { return "", err } return compact.Serialize(header, encryptedCek, iv, cipherText, authTag), nil }
// Sign produces signed JWT token given arbitrary payload, signature algorithm to use (see constants for list of supported algs) and signing key. // Signing key is of different type for different signing alg, see specific // signing alg implementation documentation. // // It returns 3 parts signed JWT token as string and not nil error if something went wrong. func Sign(payload string, signingAlg string, key interface{}) (token string, err error) { if signer, ok := jwsHashers[signingAlg]; ok { jwtHeader := map[string]interface{}{ "typ": "JWT", "alg": signingAlg, } paloadBytes := []byte(payload) var header []byte var signature []byte if header, err = json.Marshal(jwtHeader); err == nil { securedInput := []byte(compact.Serialize(header, paloadBytes)) if signature, err = signer.Sign(securedInput, key); err == nil { return compact.Serialize(header, paloadBytes, signature), nil } } return "", err } return "", errors.New(fmt.Sprintf("jwt.Sign(): unknown algorithm: '%v'", signingAlg)) }
// Sign produces signed JWT token given arbitrary payload, signature algorithm to use (see constants for list of supported algs), signing key and extra options (see option functions) // Signing key is of different type for different signing alg, see specific // signing alg implementation documentation. // // It returns 3 parts signed JWT token as string and not nil error if something went wrong. func Sign(payload string, signingAlg string, key interface{}, options ...func(*joseConfig)) (token string, err error) { if signer, ok := jwsHashers[signingAlg]; ok { cfg := &joseConfig{compressionAlg: "", headers: make(map[string]interface{})} //apply extra options for _, option := range options { option(cfg) } //make sure defaults and requires are managed by us cfg.headers["alg"] = signingAlg if _, typ := cfg.headers["typ"]; !typ { cfg.headers["typ"] = "JWT" } paloadBytes := []byte(payload) var header []byte var signature []byte if header, err = json.Marshal(cfg.headers); err == nil { securedInput := []byte(compact.Serialize(header, paloadBytes)) if signature, err = signer.Sign(securedInput, key); err == nil { return compact.Serialize(header, paloadBytes, signature), nil } } return "", err } return "", errors.New(fmt.Sprintf("jwt.Sign(): unknown algorithm: '%v'", signingAlg)) }
func verify(parts [][]byte, key interface{}) (plainText string, headers map[string]interface{}, err error) { header, payload, signature := parts[0], parts[1], parts[2] secured := []byte(compact.Serialize(header, payload)) var jwtHeader map[string]interface{} if err = json.Unmarshal(header, &jwtHeader); err != nil { return "", nil, err } alg := jwtHeader["alg"].(string) if verifier, ok := jwsHashers[alg]; ok { key = retrieveActualKey(jwtHeader, string(payload), key) if err = verifier.Verify(secured, signature, key); err == nil { return string(payload), jwtHeader, nil } return "", nil, err } return "", nil, errors.New(fmt.Sprintf("jwt.Decode(): Unknown algorithm: '%v'", alg)) }
func decrypt(parts [][]byte, key interface{}) (plainText []byte, headers map[string]interface{}, err error) { header, encryptedCek, iv, cipherText, authTag := parts[0], parts[1], parts[2], parts[3], parts[4] var jwtHeader map[string]interface{} if e := json.Unmarshal(header, &jwtHeader); e != nil { return nil, nil, e } var keyMgmtAlg JwaAlgorithm var encAlg JweEncryption var zipAlg JwcAlgorithm var cek, plainBytes []byte var ok bool var alg, enc string if alg, ok = jwtHeader["alg"].(string); !ok { return nil, nil, errors.New(fmt.Sprint("jwt.Decode(): required 'alg' header is missing or of invalid type")) } if enc, ok = jwtHeader["enc"].(string); !ok { return nil, nil, errors.New(fmt.Sprint("jwt.Decode(): required 'enc' header is missing or of invalid type")) } aad := []byte(compact.Serialize(header)) if keyMgmtAlg, ok = jwaAlgorithms[alg]; ok { if encAlg, ok = jweEncryptors[enc]; ok { if key, err = retrieveActualKey(jwtHeader, string(cipherText), key); err != nil { return nil, nil, err } if cek, err = keyMgmtAlg.Unwrap(encryptedCek, key, encAlg.KeySizeBits(), jwtHeader); err == nil { if plainBytes, err = encAlg.Decrypt(aad, cek, iv, cipherText, authTag); err == nil { if zip, compressed := jwtHeader["zip"].(string); compressed { if zipAlg, ok = jwcCompressors[zip]; !ok { return nil, nil, errors.New(fmt.Sprintf("jwt.decrypt(): Unknown compression algorithm '%v'", zip)) } plainBytes = zipAlg.Decompress(plainBytes) } return plainBytes, jwtHeader, nil } return nil, nil, err } return nil, nil, err } return nil, nil, errors.New(fmt.Sprintf("jwt.decrypt(): Unknown encryption algorithm '%v'", enc)) } return nil, nil, errors.New(fmt.Sprintf("jwt.decrypt(): Unknown key management algorithm '%v'", alg)) }
func verify(parts [][]byte, key interface{}) (plainText []byte, headers map[string]interface{}, err error) { header, payload, signature := parts[0], parts[1], parts[2] secured := []byte(compact.Serialize(header, payload)) var jwtHeader map[string]interface{} if err = json.Unmarshal(header, &jwtHeader); err != nil { return nil, nil, err } if alg, ok := jwtHeader["alg"].(string); ok { if verifier, ok := jwsHashers[alg]; ok { if key, err = retrieveActualKey(jwtHeader, string(payload), key); err != nil { return nil, nil, err } if err = verifier.Verify(secured, signature, key); err == nil { return payload, jwtHeader, nil } return nil, nil, err } return nil, nil, errors.New(fmt.Sprintf("jwt.Decode(): Unknown algorithm: '%v'", alg)) } return nil, nil, errors.New(fmt.Sprint("jwt.Decode(): required 'alg' header is missing or of invalid type")) }