mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Switch to gopkg.in/go-jose/go-jose.v2 @ v2.6.3
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
		
							
								
								
									
										206
									
								
								LICENSES/vendor/gopkg.in/go-jose/go-jose.v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								LICENSES/vendor/gopkg.in/go-jose/go-jose.v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,206 @@
 | 
			
		||||
= vendor/gopkg.in/go-jose/go-jose.v2 licensed under: =
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                                 Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
   APPENDIX: How to apply the Apache License to your work.
 | 
			
		||||
 | 
			
		||||
      To apply the Apache License to your work, attach the following
 | 
			
		||||
      boilerplate notice, with the fields enclosed by brackets "[]"
 | 
			
		||||
      replaced with your own identifying information. (Don't include
 | 
			
		||||
      the brackets!)  The text should be enclosed in the appropriate
 | 
			
		||||
      comment syntax for the file format. We also recommend that a
 | 
			
		||||
      file or class name and description of purpose be included on the
 | 
			
		||||
      same "printed page" as the copyright notice for easier
 | 
			
		||||
      identification within third-party archives.
 | 
			
		||||
 | 
			
		||||
   Copyright [yyyy] [name of copyright owner]
 | 
			
		||||
 | 
			
		||||
   Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
   you may not use this file except in compliance with the License.
 | 
			
		||||
   You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
       http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
   Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
   distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
   See the License for the specific language governing permissions and
 | 
			
		||||
   limitations under the License.
 | 
			
		||||
 | 
			
		||||
= vendor/gopkg.in/go-jose/go-jose.v2/LICENSE 3b83ef96387f14655fc854ddc3c6bd57
 | 
			
		||||
							
								
								
									
										3
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							@@ -86,7 +86,7 @@ require (
 | 
			
		||||
	google.golang.org/grpc v1.65.0
 | 
			
		||||
	google.golang.org/protobuf v1.35.1
 | 
			
		||||
	gopkg.in/evanphx/json-patch.v4 v4.12.0
 | 
			
		||||
	gopkg.in/square/go-jose.v2 v2.6.0
 | 
			
		||||
	gopkg.in/go-jose/go-jose.v2 v2.6.3
 | 
			
		||||
	k8s.io/api v0.0.0
 | 
			
		||||
	k8s.io/apiextensions-apiserver v0.0.0
 | 
			
		||||
	k8s.io/apimachinery v0.0.0
 | 
			
		||||
@@ -212,6 +212,7 @@ require (
 | 
			
		||||
	google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 // indirect
 | 
			
		||||
	gopkg.in/inf.v0 v0.9.1 // indirect
 | 
			
		||||
	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 | 
			
		||||
	gopkg.in/square/go-jose.v2 v2.6.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
	k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 // indirect
 | 
			
		||||
	sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1 // indirect
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@@ -636,6 +636,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/fields"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/google/uuid"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apiserver/pkg/audit"
 | 
			
		||||
	apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount"
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	apierrors "k8s.io/apimachinery/pkg/api/errors"
 | 
			
		||||
 
 | 
			
		||||
@@ -27,8 +27,8 @@ import (
 | 
			
		||||
 | 
			
		||||
	"google.golang.org/grpc"
 | 
			
		||||
	"google.golang.org/grpc/credentials/insecure"
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	externaljwtv1alpha1 "k8s.io/externaljwt/apis/v1alpha1"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/serviceaccount"
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ import (
 | 
			
		||||
	"google.golang.org/grpc"
 | 
			
		||||
	"google.golang.org/grpc/credentials/insecure"
 | 
			
		||||
	"google.golang.org/protobuf/types/known/timestamppb"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/serviceaccount"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,8 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ import (
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/errors"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	restful "github.com/emicklei/go-restful/v3"
 | 
			
		||||
	"github.com/google/go-cmp/cmp"
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/routes"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/serviceaccount"
 | 
			
		||||
 
 | 
			
		||||
@@ -490,6 +490,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
@@ -49,8 +49,8 @@ require (
 | 
			
		||||
	google.golang.org/grpc v1.65.0
 | 
			
		||||
	google.golang.org/protobuf v1.35.1
 | 
			
		||||
	gopkg.in/evanphx/json-patch.v4 v4.12.0
 | 
			
		||||
	gopkg.in/go-jose/go-jose.v2 v2.6.3
 | 
			
		||||
	gopkg.in/natefinch/lumberjack.v2 v2.2.1
 | 
			
		||||
	gopkg.in/square/go-jose.v2 v2.6.0
 | 
			
		||||
	k8s.io/api v0.0.0
 | 
			
		||||
	k8s.io/apimachinery v0.0.0
 | 
			
		||||
	k8s.io/client-go v0.0.0
 | 
			
		||||
@@ -122,6 +122,7 @@ require (
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
 | 
			
		||||
	google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect
 | 
			
		||||
	gopkg.in/inf.v0 v0.9.1 // indirect
 | 
			
		||||
	gopkg.in/square/go-jose.v2 v2.6.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								staging/src/k8s.io/apiserver/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								staging/src/k8s.io/apiserver/go.sum
									
									
									
										generated
									
									
									
								
							@@ -490,6 +490,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ import (
 | 
			
		||||
	"text/template"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
			
		||||
	"k8s.io/apiserver/pkg/apis/apiserver"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								staging/src/k8s.io/cloud-provider/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								staging/src/k8s.io/cloud-provider/go.sum
									
									
									
										generated
									
									
									
								
							@@ -288,6 +288,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ godebug winsymlink=0
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/stretchr/testify v1.9.0
 | 
			
		||||
	gopkg.in/square/go-jose.v2 v2.6.0
 | 
			
		||||
	gopkg.in/go-jose/go-jose.v2 v2.6.3
 | 
			
		||||
	k8s.io/api v0.0.0
 | 
			
		||||
	k8s.io/apimachinery v0.0.0
 | 
			
		||||
	k8s.io/klog/v2 v2.130.1
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								staging/src/k8s.io/cluster-bootstrap/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								staging/src/k8s.io/cluster-bootstrap/go.sum
									
									
									
										generated
									
									
									
								
							@@ -99,10 +99,10 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
 | 
			
		||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ComputeDetachedSignature takes content and token details and computes a detached
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								staging/src/k8s.io/controller-manager/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								staging/src/k8s.io/controller-manager/go.sum
									
									
									
										generated
									
									
									
								
							@@ -283,6 +283,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
@@ -236,6 +236,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								staging/src/k8s.io/kube-aggregator/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								staging/src/k8s.io/kube-aggregator/go.sum
									
									
									
										generated
									
									
									
								
							@@ -289,6 +289,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								staging/src/k8s.io/kubelet/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								staging/src/k8s.io/kubelet/go.sum
									
									
									
										generated
									
									
									
								
							@@ -221,6 +221,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								staging/src/k8s.io/pod-security-admission/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								staging/src/k8s.io/pod-security-admission/go.sum
									
									
									
										generated
									
									
									
								
							@@ -283,6 +283,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								staging/src/k8s.io/sample-apiserver/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								staging/src/k8s.io/sample-apiserver/go.sum
									
									
									
										generated
									
									
									
								
							@@ -286,6 +286,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 | 
			
		||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ import (
 | 
			
		||||
	"github.com/coreos/go-oidc"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
			
		||||
	"k8s.io/client-go/rest"
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ import (
 | 
			
		||||
	"github.com/google/go-cmp/cmp"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
 | 
			
		||||
	authenticationv1 "k8s.io/api/authentication/v1"
 | 
			
		||||
	rbacv1 "k8s.io/api/rbac/v1"
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,8 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
			
		||||
 | 
			
		||||
	authenticationv1 "k8s.io/api/authentication/v1"
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ limitations under the License.
 | 
			
		||||
package handlers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Token struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ package handlers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	mock "github.com/stretchr/testify/mock"
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MockJWKsHandler is an autogenerated mock type for the JWKsHandler type
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
	"k8s.io/kubernetes/test/utils/oidc/handlers"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/.gitcookies.sh.enc
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/.gitcookies.sh.enc
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
'|<7C>&{t<>U|gG<67>(<1E><>Cy=+<13><><EFBFBD>c<EFBFBD>:u:/p<>#~<7E><>["<22>4<EFBFBD>!<21>n<EFBFBD>A<EFBFBD>DK<<3C>uf<75>h<>a<EFBFBD><14>:<3A><><EFBFBD><EFBFBD><EFBFBD>B/<2F>ؤ<EFBFBD><D8A4><08>_<EFBFBD>h<EFBFBD><68>S<17>T*w<>x<EFBFBD><78><12><>-<2D>|<7C><><EFBFBD>Ӄ<EFBFBD><D383><EFBFBD><EFBFBD><14>㣗A$$<24>6<EFBFBD><36><03>G)8n<38>p<EFBFBD><12>ˡ3̚<33>o<><6F>v<>B<>3<EFBFBD><33>]xݓ<78>2l<>G<EFBFBD>|qRޯ
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
*~
 | 
			
		||||
.*.swp
 | 
			
		||||
*.out
 | 
			
		||||
*.test
 | 
			
		||||
*.pem
 | 
			
		||||
*.cov
 | 
			
		||||
jose-util/jose-util
 | 
			
		||||
jose-util.t.err
 | 
			
		||||
							
								
								
									
										45
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
language: go
 | 
			
		||||
 | 
			
		||||
sudo: false
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
  fast_finish: true
 | 
			
		||||
  allow_failures:
 | 
			
		||||
    - go: tip
 | 
			
		||||
 | 
			
		||||
go:
 | 
			
		||||
- '1.14.x'
 | 
			
		||||
- '1.15.x'
 | 
			
		||||
- tip
 | 
			
		||||
 | 
			
		||||
go_import_path: gopkg.in/square/go-jose.v2
 | 
			
		||||
 | 
			
		||||
before_script:
 | 
			
		||||
- export PATH=$HOME/.local/bin:$PATH
 | 
			
		||||
 | 
			
		||||
before_install:
 | 
			
		||||
# Install encrypted gitcookies to get around bandwidth-limits
 | 
			
		||||
# that is causing Travis-CI builds to fail. For more info, see
 | 
			
		||||
# https://github.com/golang/go/issues/12933
 | 
			
		||||
- openssl aes-256-cbc -K $encrypted_1528c3c2cafd_key -iv $encrypted_1528c3c2cafd_iv -in .gitcookies.sh.enc -out .gitcookies.sh -d || true
 | 
			
		||||
- bash .gitcookies.sh || true
 | 
			
		||||
- go get github.com/wadey/gocovmerge
 | 
			
		||||
- go get github.com/mattn/goveralls
 | 
			
		||||
- go get github.com/stretchr/testify/assert
 | 
			
		||||
- go get github.com/stretchr/testify/require
 | 
			
		||||
- go get github.com/google/go-cmp/cmp
 | 
			
		||||
- go get golang.org/x/tools/cmd/cover || true
 | 
			
		||||
- go get code.google.com/p/go.tools/cmd/cover || true
 | 
			
		||||
- pip install cram --user
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
- go test . -v -covermode=count -coverprofile=profile.cov
 | 
			
		||||
- go test ./cipher -v -covermode=count -coverprofile=cipher/profile.cov
 | 
			
		||||
- go test ./jwt -v -covermode=count -coverprofile=jwt/profile.cov
 | 
			
		||||
- go test ./json -v # no coverage for forked encoding/json package
 | 
			
		||||
- cd jose-util && go build && PATH=$PWD:$PATH cram -v jose-util.t # cram tests jose-util
 | 
			
		||||
- cd ..
 | 
			
		||||
 | 
			
		||||
after_success:
 | 
			
		||||
- gocovmerge *.cov */*.cov > merged.coverprofile
 | 
			
		||||
- $HOME/gopath/bin/goveralls -coverprofile merged.coverprofile -service=travis-ci
 | 
			
		||||
							
								
								
									
										84
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
# v4.0.1
 | 
			
		||||
 | 
			
		||||
## Fixed
 | 
			
		||||
 | 
			
		||||
 - An attacker could send a JWE containing compressed data that used large
 | 
			
		||||
   amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`.
 | 
			
		||||
   Those functions now return an error if the decompressed data would exceed
 | 
			
		||||
   250kB or 10x the compressed size (whichever is larger). Thanks to
 | 
			
		||||
   Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj)
 | 
			
		||||
   for reporting.
 | 
			
		||||
 | 
			
		||||
# v4.0.0
 | 
			
		||||
 | 
			
		||||
This release makes some breaking changes in order to more thoroughly
 | 
			
		||||
address the vulnerabilities discussed in [Three New Attacks Against JSON Web
 | 
			
		||||
Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot
 | 
			
		||||
token".
 | 
			
		||||
 | 
			
		||||
## Changed
 | 
			
		||||
 | 
			
		||||
 - Limit JWT encryption types (exclude password or public key types) (#78)
 | 
			
		||||
 - Enforce minimum length for HMAC keys (#85)
 | 
			
		||||
 - jwt: match any audience in a list, rather than requiring all audiences (#81)
 | 
			
		||||
 - jwt: accept only Compact Serialization (#75)
 | 
			
		||||
 - jws: Add expected algorithms for signatures (#74)
 | 
			
		||||
 - Require specifying expected algorithms for ParseEncrypted,
 | 
			
		||||
   ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned,
 | 
			
		||||
   jwt.ParseSignedAndEncrypted (#69, #74)
 | 
			
		||||
   - Usually there is a small, known set of appropriate algorithms for a program
 | 
			
		||||
     to use and it's a mistake to allow unexpected algorithms. For instance the
 | 
			
		||||
     "billion hash attack" relies in part on programs accepting the PBES2
 | 
			
		||||
     encryption algorithm and doing the necessary work even if they weren't
 | 
			
		||||
     specifically configured to allow PBES2.
 | 
			
		||||
 - Revert "Strip padding off base64 strings" (#82)
 | 
			
		||||
  - The specs require base64url encoding without padding.
 | 
			
		||||
 - Minimum supported Go version is now 1.21
 | 
			
		||||
 | 
			
		||||
## Added
 | 
			
		||||
 | 
			
		||||
 - ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON.
 | 
			
		||||
   - These allow parsing a specific serialization, as opposed to ParseSigned and
 | 
			
		||||
     ParseEncrypted, which try to automatically detect which serialization was
 | 
			
		||||
     provided. It's common to require a specific serialization for a specific
 | 
			
		||||
     protocol - for instance JWT requires Compact serialization.
 | 
			
		||||
 | 
			
		||||
[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
 | 
			
		||||
 | 
			
		||||
# v3.0.3
 | 
			
		||||
 | 
			
		||||
## Fixed
 | 
			
		||||
 | 
			
		||||
 - Limit decompression output size to prevent a DoS. Backport from v4.0.1.
 | 
			
		||||
 | 
			
		||||
# v3.0.2
 | 
			
		||||
 | 
			
		||||
## Fixed
 | 
			
		||||
 | 
			
		||||
 - DecryptMulti: handle decompression error (#19)
 | 
			
		||||
 | 
			
		||||
## Changed
 | 
			
		||||
 | 
			
		||||
 - jwe/CompactSerialize: improve performance (#67)
 | 
			
		||||
 - Increase the default number of PBKDF2 iterations to 600k (#48)
 | 
			
		||||
 - Return the proper algorithm for ECDSA keys (#45)
 | 
			
		||||
 | 
			
		||||
## Added
 | 
			
		||||
 | 
			
		||||
 - Add Thumbprint support for opaque signers (#38)
 | 
			
		||||
 | 
			
		||||
# v3.0.1
 | 
			
		||||
 | 
			
		||||
## Fixed
 | 
			
		||||
 | 
			
		||||
 - Security issue: an attacker specifying a large "p2c" value can cause
 | 
			
		||||
   JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
 | 
			
		||||
   amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the
 | 
			
		||||
   disclosure and to Tom Tervoort for originally publishing the category of attack.
 | 
			
		||||
   https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
 | 
			
		||||
 | 
			
		||||
# v2.6.3
 | 
			
		||||
 | 
			
		||||
## Fixed
 | 
			
		||||
 | 
			
		||||
 - Limit decompression output size to prevent a DoS. Backport from v4.0.1.
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
# Contributing
 | 
			
		||||
 | 
			
		||||
If you would like to contribute code to go-jose you can do so through GitHub by
 | 
			
		||||
forking the repository and sending a pull request.
 | 
			
		||||
 | 
			
		||||
When submitting code, please make every effort to follow existing conventions
 | 
			
		||||
and style in order to keep the code as readable as possible. Please also make
 | 
			
		||||
sure all tests pass by running `go test`, and format your code with `go fmt`.
 | 
			
		||||
We also recommend using `golint` and `errcheck`.
 | 
			
		||||
 | 
			
		||||
Before your code can be accepted into the project you must also sign the
 | 
			
		||||
[Individual Contributor License Agreement][1].
 | 
			
		||||
 | 
			
		||||
 [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1
 | 
			
		||||
							
								
								
									
										202
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
 | 
			
		||||
                                 Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
   APPENDIX: How to apply the Apache License to your work.
 | 
			
		||||
 | 
			
		||||
      To apply the Apache License to your work, attach the following
 | 
			
		||||
      boilerplate notice, with the fields enclosed by brackets "[]"
 | 
			
		||||
      replaced with your own identifying information. (Don't include
 | 
			
		||||
      the brackets!)  The text should be enclosed in the appropriate
 | 
			
		||||
      comment syntax for the file format. We also recommend that a
 | 
			
		||||
      file or class name and description of purpose be included on the
 | 
			
		||||
      same "printed page" as the copyright notice for easier
 | 
			
		||||
      identification within third-party archives.
 | 
			
		||||
 | 
			
		||||
   Copyright [yyyy] [name of copyright owner]
 | 
			
		||||
 | 
			
		||||
   Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
   you may not use this file except in compliance with the License.
 | 
			
		||||
   You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
       http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
   Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
   distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
   See the License for the specific language governing permissions and
 | 
			
		||||
   limitations under the License.
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# go-jose v2
 | 
			
		||||
 | 
			
		||||
Version 2 of this library is no longer supported. [Please use v4
 | 
			
		||||
instead](https://pkg.go.dev/github.com/go-jose/go-jose/v4).
 | 
			
		||||
							
								
								
									
										595
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/asymmetric.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										595
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/asymmetric.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,595 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto"
 | 
			
		||||
	"crypto/aes"
 | 
			
		||||
	"crypto/ecdsa"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"crypto/sha1"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/big"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/ed25519"
 | 
			
		||||
	josecipher "gopkg.in/go-jose/go-jose.v2/cipher"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A generic RSA-based encrypter/verifier
 | 
			
		||||
type rsaEncrypterVerifier struct {
 | 
			
		||||
	publicKey *rsa.PublicKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A generic RSA-based decrypter/signer
 | 
			
		||||
type rsaDecrypterSigner struct {
 | 
			
		||||
	privateKey *rsa.PrivateKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A generic EC-based encrypter/verifier
 | 
			
		||||
type ecEncrypterVerifier struct {
 | 
			
		||||
	publicKey *ecdsa.PublicKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type edEncrypterVerifier struct {
 | 
			
		||||
	publicKey ed25519.PublicKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A key generator for ECDH-ES
 | 
			
		||||
type ecKeyGenerator struct {
 | 
			
		||||
	size      int
 | 
			
		||||
	algID     string
 | 
			
		||||
	publicKey *ecdsa.PublicKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A generic EC-based decrypter/signer
 | 
			
		||||
type ecDecrypterSigner struct {
 | 
			
		||||
	privateKey *ecdsa.PrivateKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type edDecrypterSigner struct {
 | 
			
		||||
	privateKey ed25519.PrivateKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newRSARecipient creates recipientKeyInfo based on the given key.
 | 
			
		||||
func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) {
 | 
			
		||||
	// Verify that key management algorithm is supported by this encrypter
 | 
			
		||||
	switch keyAlg {
 | 
			
		||||
	case RSA1_5, RSA_OAEP, RSA_OAEP_256:
 | 
			
		||||
	default:
 | 
			
		||||
		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if publicKey == nil {
 | 
			
		||||
		return recipientKeyInfo{}, errors.New("invalid public key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientKeyInfo{
 | 
			
		||||
		keyAlg: keyAlg,
 | 
			
		||||
		keyEncrypter: &rsaEncrypterVerifier{
 | 
			
		||||
			publicKey: publicKey,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newRSASigner creates a recipientSigInfo based on the given key.
 | 
			
		||||
func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipientSigInfo, error) {
 | 
			
		||||
	// Verify that key management algorithm is supported by this encrypter
 | 
			
		||||
	switch sigAlg {
 | 
			
		||||
	case RS256, RS384, RS512, PS256, PS384, PS512:
 | 
			
		||||
	default:
 | 
			
		||||
		return recipientSigInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if privateKey == nil {
 | 
			
		||||
		return recipientSigInfo{}, errors.New("invalid private key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientSigInfo{
 | 
			
		||||
		sigAlg: sigAlg,
 | 
			
		||||
		publicKey: staticPublicKey(&JSONWebKey{
 | 
			
		||||
			Key: privateKey.Public(),
 | 
			
		||||
		}),
 | 
			
		||||
		signer: &rsaDecrypterSigner{
 | 
			
		||||
			privateKey: privateKey,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newEd25519Signer(sigAlg SignatureAlgorithm, privateKey ed25519.PrivateKey) (recipientSigInfo, error) {
 | 
			
		||||
	if sigAlg != EdDSA {
 | 
			
		||||
		return recipientSigInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if privateKey == nil {
 | 
			
		||||
		return recipientSigInfo{}, errors.New("invalid private key")
 | 
			
		||||
	}
 | 
			
		||||
	return recipientSigInfo{
 | 
			
		||||
		sigAlg: sigAlg,
 | 
			
		||||
		publicKey: staticPublicKey(&JSONWebKey{
 | 
			
		||||
			Key: privateKey.Public(),
 | 
			
		||||
		}),
 | 
			
		||||
		signer: &edDecrypterSigner{
 | 
			
		||||
			privateKey: privateKey,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newECDHRecipient creates recipientKeyInfo based on the given key.
 | 
			
		||||
func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) {
 | 
			
		||||
	// Verify that key management algorithm is supported by this encrypter
 | 
			
		||||
	switch keyAlg {
 | 
			
		||||
	case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
 | 
			
		||||
	default:
 | 
			
		||||
		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
 | 
			
		||||
		return recipientKeyInfo{}, errors.New("invalid public key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientKeyInfo{
 | 
			
		||||
		keyAlg: keyAlg,
 | 
			
		||||
		keyEncrypter: &ecEncrypterVerifier{
 | 
			
		||||
			publicKey: publicKey,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newECDSASigner creates a recipientSigInfo based on the given key.
 | 
			
		||||
func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (recipientSigInfo, error) {
 | 
			
		||||
	// Verify that key management algorithm is supported by this encrypter
 | 
			
		||||
	switch sigAlg {
 | 
			
		||||
	case ES256, ES384, ES512:
 | 
			
		||||
	default:
 | 
			
		||||
		return recipientSigInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if privateKey == nil {
 | 
			
		||||
		return recipientSigInfo{}, errors.New("invalid private key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientSigInfo{
 | 
			
		||||
		sigAlg: sigAlg,
 | 
			
		||||
		publicKey: staticPublicKey(&JSONWebKey{
 | 
			
		||||
			Key: privateKey.Public(),
 | 
			
		||||
		}),
 | 
			
		||||
		signer: &ecDecrypterSigner{
 | 
			
		||||
			privateKey: privateKey,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encrypt the given payload and update the object.
 | 
			
		||||
func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
 | 
			
		||||
	encryptedKey, err := ctx.encrypt(cek, alg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return recipientInfo{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientInfo{
 | 
			
		||||
		encryptedKey: encryptedKey,
 | 
			
		||||
		header:       &rawHeader{},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encrypt the given payload. Based on the key encryption algorithm,
 | 
			
		||||
// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
 | 
			
		||||
func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) {
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case RSA1_5:
 | 
			
		||||
		return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek)
 | 
			
		||||
	case RSA_OAEP:
 | 
			
		||||
		return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{})
 | 
			
		||||
	case RSA_OAEP_256:
 | 
			
		||||
		return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decrypt the given payload and return the content encryption key.
 | 
			
		||||
func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
 | 
			
		||||
	return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decrypt the given payload. Based on the key encryption algorithm,
 | 
			
		||||
// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
 | 
			
		||||
func (ctx rsaDecrypterSigner) decrypt(jek []byte, alg KeyAlgorithm, generator keyGenerator) ([]byte, error) {
 | 
			
		||||
	// Note: The random reader on decrypt operations is only used for blinding,
 | 
			
		||||
	// so stubbing is meanlingless (hence the direct use of rand.Reader).
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case RSA1_5:
 | 
			
		||||
		defer func() {
 | 
			
		||||
			// DecryptPKCS1v15SessionKey sometimes panics on an invalid payload
 | 
			
		||||
			// because of an index out of bounds error, which we want to ignore.
 | 
			
		||||
			// This has been fixed in Go 1.3.1 (released 2014/08/13), the recover()
 | 
			
		||||
			// only exists for preventing crashes with unpatched versions.
 | 
			
		||||
			// See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k
 | 
			
		||||
			// See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33
 | 
			
		||||
			_ = recover()
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		// Perform some input validation.
 | 
			
		||||
		keyBytes := ctx.privateKey.PublicKey.N.BitLen() / 8
 | 
			
		||||
		if keyBytes != len(jek) {
 | 
			
		||||
			// Input size is incorrect, the encrypted payload should always match
 | 
			
		||||
			// the size of the public modulus (e.g. using a 2048 bit key will
 | 
			
		||||
			// produce 256 bytes of output). Reject this since it's invalid input.
 | 
			
		||||
			return nil, ErrCryptoFailure
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cek, _, err := generator.genKey()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, ErrCryptoFailure
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to
 | 
			
		||||
		// prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing
 | 
			
		||||
		// the Million Message Attack on Cryptographic Message Syntax". We are
 | 
			
		||||
		// therefore deliberately ignoring errors here.
 | 
			
		||||
		_ = rsa.DecryptPKCS1v15SessionKey(rand.Reader, ctx.privateKey, jek, cek)
 | 
			
		||||
 | 
			
		||||
		return cek, nil
 | 
			
		||||
	case RSA_OAEP:
 | 
			
		||||
		// Use rand.Reader for RSA blinding
 | 
			
		||||
		return rsa.DecryptOAEP(sha1.New(), rand.Reader, ctx.privateKey, jek, []byte{})
 | 
			
		||||
	case RSA_OAEP_256:
 | 
			
		||||
		// Use rand.Reader for RSA blinding
 | 
			
		||||
		return rsa.DecryptOAEP(sha256.New(), rand.Reader, ctx.privateKey, jek, []byte{})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sign the given payload
 | 
			
		||||
func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
 | 
			
		||||
	var hash crypto.Hash
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case RS256, PS256:
 | 
			
		||||
		hash = crypto.SHA256
 | 
			
		||||
	case RS384, PS384:
 | 
			
		||||
		hash = crypto.SHA384
 | 
			
		||||
	case RS512, PS512:
 | 
			
		||||
		hash = crypto.SHA512
 | 
			
		||||
	default:
 | 
			
		||||
		return Signature{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hasher := hash.New()
 | 
			
		||||
 | 
			
		||||
	// According to documentation, Write() on hash never fails
 | 
			
		||||
	_, _ = hasher.Write(payload)
 | 
			
		||||
	hashed := hasher.Sum(nil)
 | 
			
		||||
 | 
			
		||||
	var out []byte
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case RS256, RS384, RS512:
 | 
			
		||||
		// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
 | 
			
		||||
		// random parameter is legacy and ignored, and it can be nil.
 | 
			
		||||
		// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
 | 
			
		||||
		out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
 | 
			
		||||
	case PS256, PS384, PS512:
 | 
			
		||||
		out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
 | 
			
		||||
			SaltLength: rsa.PSSSaltLengthEqualsHash,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Signature{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Signature{
 | 
			
		||||
		Signature: out,
 | 
			
		||||
		protected: &rawHeader{},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Verify the given payload
 | 
			
		||||
func (ctx rsaEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
 | 
			
		||||
	var hash crypto.Hash
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case RS256, PS256:
 | 
			
		||||
		hash = crypto.SHA256
 | 
			
		||||
	case RS384, PS384:
 | 
			
		||||
		hash = crypto.SHA384
 | 
			
		||||
	case RS512, PS512:
 | 
			
		||||
		hash = crypto.SHA512
 | 
			
		||||
	default:
 | 
			
		||||
		return ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hasher := hash.New()
 | 
			
		||||
 | 
			
		||||
	// According to documentation, Write() on hash never fails
 | 
			
		||||
	_, _ = hasher.Write(payload)
 | 
			
		||||
	hashed := hasher.Sum(nil)
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case RS256, RS384, RS512:
 | 
			
		||||
		return rsa.VerifyPKCS1v15(ctx.publicKey, hash, hashed, signature)
 | 
			
		||||
	case PS256, PS384, PS512:
 | 
			
		||||
		return rsa.VerifyPSS(ctx.publicKey, hash, hashed, signature, nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ErrUnsupportedAlgorithm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encrypt the given payload and update the object.
 | 
			
		||||
func (ctx ecEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case ECDH_ES:
 | 
			
		||||
		// ECDH-ES mode doesn't wrap a key, the shared secret is used directly as the key.
 | 
			
		||||
		return recipientInfo{
 | 
			
		||||
			header: &rawHeader{},
 | 
			
		||||
		}, nil
 | 
			
		||||
	case ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
 | 
			
		||||
	default:
 | 
			
		||||
		return recipientInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	generator := ecKeyGenerator{
 | 
			
		||||
		algID:     string(alg),
 | 
			
		||||
		publicKey: ctx.publicKey,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case ECDH_ES_A128KW:
 | 
			
		||||
		generator.size = 16
 | 
			
		||||
	case ECDH_ES_A192KW:
 | 
			
		||||
		generator.size = 24
 | 
			
		||||
	case ECDH_ES_A256KW:
 | 
			
		||||
		generator.size = 32
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	kek, header, err := generator.genKey()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return recipientInfo{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block, err := aes.NewCipher(kek)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return recipientInfo{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jek, err := josecipher.KeyWrap(block, cek)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return recipientInfo{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientInfo{
 | 
			
		||||
		encryptedKey: jek,
 | 
			
		||||
		header:       &header,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get key size for EC key generator
 | 
			
		||||
func (ctx ecKeyGenerator) keySize() int {
 | 
			
		||||
	return ctx.size
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get a content encryption key for ECDH-ES
 | 
			
		||||
func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
 | 
			
		||||
	priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, rawHeader{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size)
 | 
			
		||||
 | 
			
		||||
	b, err := json.Marshal(&JSONWebKey{
 | 
			
		||||
		Key: &priv.PublicKey,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	headers := rawHeader{
 | 
			
		||||
		headerEPK: makeRawMessage(b),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, headers, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decrypt the given payload and return the content encryption key.
 | 
			
		||||
func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
 | 
			
		||||
	epk, err := headers.getEPK()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid epk header")
 | 
			
		||||
	}
 | 
			
		||||
	if epk == nil {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: missing epk header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	publicKey, ok := epk.Key.(*ecdsa.PublicKey)
 | 
			
		||||
	if publicKey == nil || !ok {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid epk header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid public key in epk header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apuData, err := headers.getAPU()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid apu header")
 | 
			
		||||
	}
 | 
			
		||||
	apvData, err := headers.getAPV()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid apv header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	deriveKey := func(algID string, size int) []byte {
 | 
			
		||||
		return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var keySize int
 | 
			
		||||
 | 
			
		||||
	algorithm := headers.getAlgorithm()
 | 
			
		||||
	switch algorithm {
 | 
			
		||||
	case ECDH_ES:
 | 
			
		||||
		// ECDH-ES uses direct key agreement, no key unwrapping necessary.
 | 
			
		||||
		return deriveKey(string(headers.getEncryption()), generator.keySize()), nil
 | 
			
		||||
	case ECDH_ES_A128KW:
 | 
			
		||||
		keySize = 16
 | 
			
		||||
	case ECDH_ES_A192KW:
 | 
			
		||||
		keySize = 24
 | 
			
		||||
	case ECDH_ES_A256KW:
 | 
			
		||||
		keySize = 32
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key := deriveKey(string(algorithm), keySize)
 | 
			
		||||
	block, err := aes.NewCipher(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return josecipher.KeyUnwrap(block, recipient.encryptedKey)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
 | 
			
		||||
	if alg != EdDSA {
 | 
			
		||||
		return Signature{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sig, err := ctx.privateKey.Sign(RandReader, payload, crypto.Hash(0))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Signature{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Signature{
 | 
			
		||||
		Signature: sig,
 | 
			
		||||
		protected: &rawHeader{},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
 | 
			
		||||
	if alg != EdDSA {
 | 
			
		||||
		return ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
	ok := ed25519.Verify(ctx.publicKey, payload, signature)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return errors.New("go-jose/go-jose: ed25519 signature failed to verify")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sign the given payload
 | 
			
		||||
func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
 | 
			
		||||
	var expectedBitSize int
 | 
			
		||||
	var hash crypto.Hash
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case ES256:
 | 
			
		||||
		expectedBitSize = 256
 | 
			
		||||
		hash = crypto.SHA256
 | 
			
		||||
	case ES384:
 | 
			
		||||
		expectedBitSize = 384
 | 
			
		||||
		hash = crypto.SHA384
 | 
			
		||||
	case ES512:
 | 
			
		||||
		expectedBitSize = 521
 | 
			
		||||
		hash = crypto.SHA512
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	curveBits := ctx.privateKey.Curve.Params().BitSize
 | 
			
		||||
	if expectedBitSize != curveBits {
 | 
			
		||||
		return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hasher := hash.New()
 | 
			
		||||
 | 
			
		||||
	// According to documentation, Write() on hash never fails
 | 
			
		||||
	_, _ = hasher.Write(payload)
 | 
			
		||||
	hashed := hasher.Sum(nil)
 | 
			
		||||
 | 
			
		||||
	r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Signature{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	keyBytes := curveBits / 8
 | 
			
		||||
	if curveBits%8 > 0 {
 | 
			
		||||
		keyBytes++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We serialize the outputs (r and s) into big-endian byte arrays and pad
 | 
			
		||||
	// them with zeros on the left to make sure the sizes work out. Both arrays
 | 
			
		||||
	// must be keyBytes long, and the output must be 2*keyBytes long.
 | 
			
		||||
	rBytes := r.Bytes()
 | 
			
		||||
	rBytesPadded := make([]byte, keyBytes)
 | 
			
		||||
	copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
 | 
			
		||||
 | 
			
		||||
	sBytes := s.Bytes()
 | 
			
		||||
	sBytesPadded := make([]byte, keyBytes)
 | 
			
		||||
	copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
 | 
			
		||||
 | 
			
		||||
	out := append(rBytesPadded, sBytesPadded...)
 | 
			
		||||
 | 
			
		||||
	return Signature{
 | 
			
		||||
		Signature: out,
 | 
			
		||||
		protected: &rawHeader{},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Verify the given payload
 | 
			
		||||
func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
 | 
			
		||||
	var keySize int
 | 
			
		||||
	var hash crypto.Hash
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case ES256:
 | 
			
		||||
		keySize = 32
 | 
			
		||||
		hash = crypto.SHA256
 | 
			
		||||
	case ES384:
 | 
			
		||||
		keySize = 48
 | 
			
		||||
		hash = crypto.SHA384
 | 
			
		||||
	case ES512:
 | 
			
		||||
		keySize = 66
 | 
			
		||||
		hash = crypto.SHA512
 | 
			
		||||
	default:
 | 
			
		||||
		return ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(signature) != 2*keySize {
 | 
			
		||||
		return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hasher := hash.New()
 | 
			
		||||
 | 
			
		||||
	// According to documentation, Write() on hash never fails
 | 
			
		||||
	_, _ = hasher.Write(payload)
 | 
			
		||||
	hashed := hasher.Sum(nil)
 | 
			
		||||
 | 
			
		||||
	r := big.NewInt(0).SetBytes(signature[:keySize])
 | 
			
		||||
	s := big.NewInt(0).SetBytes(signature[keySize:])
 | 
			
		||||
 | 
			
		||||
	match := ecdsa.Verify(ctx.publicKey, hashed, r, s)
 | 
			
		||||
	if !match {
 | 
			
		||||
		return errors.New("go-jose/go-jose: ecdsa signature failed to verify")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										196
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/cbc_hmac.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/cbc_hmac.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,196 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package josecipher
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto/cipher"
 | 
			
		||||
	"crypto/hmac"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"crypto/sha512"
 | 
			
		||||
	"crypto/subtle"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"hash"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	nonceBytes = 16
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewCBCHMAC instantiates a new AEAD based on CBC+HMAC.
 | 
			
		||||
func NewCBCHMAC(key []byte, newBlockCipher func([]byte) (cipher.Block, error)) (cipher.AEAD, error) {
 | 
			
		||||
	keySize := len(key) / 2
 | 
			
		||||
	integrityKey := key[:keySize]
 | 
			
		||||
	encryptionKey := key[keySize:]
 | 
			
		||||
 | 
			
		||||
	blockCipher, err := newBlockCipher(encryptionKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hash func() hash.Hash
 | 
			
		||||
	switch keySize {
 | 
			
		||||
	case 16:
 | 
			
		||||
		hash = sha256.New
 | 
			
		||||
	case 24:
 | 
			
		||||
		hash = sha512.New384
 | 
			
		||||
	case 32:
 | 
			
		||||
		hash = sha512.New
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &cbcAEAD{
 | 
			
		||||
		hash:         hash,
 | 
			
		||||
		blockCipher:  blockCipher,
 | 
			
		||||
		authtagBytes: keySize,
 | 
			
		||||
		integrityKey: integrityKey,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An AEAD based on CBC+HMAC
 | 
			
		||||
type cbcAEAD struct {
 | 
			
		||||
	hash         func() hash.Hash
 | 
			
		||||
	authtagBytes int
 | 
			
		||||
	integrityKey []byte
 | 
			
		||||
	blockCipher  cipher.Block
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *cbcAEAD) NonceSize() int {
 | 
			
		||||
	return nonceBytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *cbcAEAD) Overhead() int {
 | 
			
		||||
	// Maximum overhead is block size (for padding) plus auth tag length, where
 | 
			
		||||
	// the length of the auth tag is equivalent to the key size.
 | 
			
		||||
	return ctx.blockCipher.BlockSize() + ctx.authtagBytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Seal encrypts and authenticates the plaintext.
 | 
			
		||||
func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
 | 
			
		||||
	// Output buffer -- must take care not to mangle plaintext input.
 | 
			
		||||
	ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)]
 | 
			
		||||
	copy(ciphertext, plaintext)
 | 
			
		||||
	ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize())
 | 
			
		||||
 | 
			
		||||
	cbc := cipher.NewCBCEncrypter(ctx.blockCipher, nonce)
 | 
			
		||||
 | 
			
		||||
	cbc.CryptBlocks(ciphertext, ciphertext)
 | 
			
		||||
	authtag := ctx.computeAuthTag(data, nonce, ciphertext)
 | 
			
		||||
 | 
			
		||||
	ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag)))
 | 
			
		||||
	copy(out, ciphertext)
 | 
			
		||||
	copy(out[len(ciphertext):], authtag)
 | 
			
		||||
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open decrypts and authenticates the ciphertext.
 | 
			
		||||
func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 | 
			
		||||
	if len(ciphertext) < ctx.authtagBytes {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid ciphertext (too short)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	offset := len(ciphertext) - ctx.authtagBytes
 | 
			
		||||
	expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset])
 | 
			
		||||
	match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:])
 | 
			
		||||
	if match != 1 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid ciphertext (auth tag mismatch)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce)
 | 
			
		||||
 | 
			
		||||
	// Make copy of ciphertext buffer, don't want to modify in place
 | 
			
		||||
	buffer := append([]byte{}, []byte(ciphertext[:offset])...)
 | 
			
		||||
 | 
			
		||||
	if len(buffer)%ctx.blockCipher.BlockSize() > 0 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid ciphertext (invalid length)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cbc.CryptBlocks(buffer, buffer)
 | 
			
		||||
 | 
			
		||||
	// Remove padding
 | 
			
		||||
	plaintext, err := unpadBuffer(buffer, ctx.blockCipher.BlockSize())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext)))
 | 
			
		||||
	copy(out, plaintext)
 | 
			
		||||
 | 
			
		||||
	return ret, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compute an authentication tag
 | 
			
		||||
func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte {
 | 
			
		||||
	buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8)
 | 
			
		||||
	n := 0
 | 
			
		||||
	n += copy(buffer, aad)
 | 
			
		||||
	n += copy(buffer[n:], nonce)
 | 
			
		||||
	n += copy(buffer[n:], ciphertext)
 | 
			
		||||
	binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8)
 | 
			
		||||
 | 
			
		||||
	// According to documentation, Write() on hash.Hash never fails.
 | 
			
		||||
	hmac := hmac.New(ctx.hash, ctx.integrityKey)
 | 
			
		||||
	_, _ = hmac.Write(buffer)
 | 
			
		||||
 | 
			
		||||
	return hmac.Sum(nil)[:ctx.authtagBytes]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// resize ensures that the given slice has a capacity of at least n bytes.
 | 
			
		||||
// If the capacity of the slice is less than n, a new slice is allocated
 | 
			
		||||
// and the existing data will be copied.
 | 
			
		||||
func resize(in []byte, n uint64) (head, tail []byte) {
 | 
			
		||||
	if uint64(cap(in)) >= n {
 | 
			
		||||
		head = in[:n]
 | 
			
		||||
	} else {
 | 
			
		||||
		head = make([]byte, n)
 | 
			
		||||
		copy(head, in)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tail = head[len(in):]
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Apply padding
 | 
			
		||||
func padBuffer(buffer []byte, blockSize int) []byte {
 | 
			
		||||
	missing := blockSize - (len(buffer) % blockSize)
 | 
			
		||||
	ret, out := resize(buffer, uint64(len(buffer))+uint64(missing))
 | 
			
		||||
	padding := bytes.Repeat([]byte{byte(missing)}, missing)
 | 
			
		||||
	copy(out, padding)
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove padding
 | 
			
		||||
func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) {
 | 
			
		||||
	if len(buffer)%blockSize != 0 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid padding")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	last := buffer[len(buffer)-1]
 | 
			
		||||
	count := int(last)
 | 
			
		||||
 | 
			
		||||
	if count == 0 || count > blockSize || count > len(buffer) {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid padding")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	padding := bytes.Repeat([]byte{last}, count)
 | 
			
		||||
	if !bytes.HasSuffix(buffer, padding) {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid padding")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return buffer[:len(buffer)-count], nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/concat_kdf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/concat_kdf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package josecipher
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"hash"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type concatKDF struct {
 | 
			
		||||
	z, info []byte
 | 
			
		||||
	i       uint32
 | 
			
		||||
	cache   []byte
 | 
			
		||||
	hasher  hash.Hash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewConcatKDF builds a KDF reader based on the given inputs.
 | 
			
		||||
func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader {
 | 
			
		||||
	buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo)))
 | 
			
		||||
	n := 0
 | 
			
		||||
	n += copy(buffer, algID)
 | 
			
		||||
	n += copy(buffer[n:], ptyUInfo)
 | 
			
		||||
	n += copy(buffer[n:], ptyVInfo)
 | 
			
		||||
	n += copy(buffer[n:], supPubInfo)
 | 
			
		||||
	copy(buffer[n:], supPrivInfo)
 | 
			
		||||
 | 
			
		||||
	hasher := hash.New()
 | 
			
		||||
 | 
			
		||||
	return &concatKDF{
 | 
			
		||||
		z:      z,
 | 
			
		||||
		info:   buffer,
 | 
			
		||||
		hasher: hasher,
 | 
			
		||||
		cache:  []byte{},
 | 
			
		||||
		i:      1,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *concatKDF) Read(out []byte) (int, error) {
 | 
			
		||||
	copied := copy(out, ctx.cache)
 | 
			
		||||
	ctx.cache = ctx.cache[copied:]
 | 
			
		||||
 | 
			
		||||
	for copied < len(out) {
 | 
			
		||||
		ctx.hasher.Reset()
 | 
			
		||||
 | 
			
		||||
		// Write on a hash.Hash never fails
 | 
			
		||||
		_ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i)
 | 
			
		||||
		_, _ = ctx.hasher.Write(ctx.z)
 | 
			
		||||
		_, _ = ctx.hasher.Write(ctx.info)
 | 
			
		||||
 | 
			
		||||
		hash := ctx.hasher.Sum(nil)
 | 
			
		||||
		chunkCopied := copy(out[copied:], hash)
 | 
			
		||||
		copied += chunkCopied
 | 
			
		||||
		ctx.cache = hash[chunkCopied:]
 | 
			
		||||
 | 
			
		||||
		ctx.i++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return copied, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/ecdh_es.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/ecdh_es.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package josecipher
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto"
 | 
			
		||||
	"crypto/ecdsa"
 | 
			
		||||
	"crypto/elliptic"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA.
 | 
			
		||||
// It is an error to call this function with a private/public key that are not on the same
 | 
			
		||||
// curve. Callers must ensure that the keys are valid before calling this function. Output
 | 
			
		||||
// size may be at most 1<<16 bytes (64 KiB).
 | 
			
		||||
func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte {
 | 
			
		||||
	if size > 1<<16 {
 | 
			
		||||
		panic("ECDH-ES output size too large, must be less than or equal to 1<<16")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// algId, partyUInfo, partyVInfo inputs must be prefixed with the length
 | 
			
		||||
	algID := lengthPrefixed([]byte(alg))
 | 
			
		||||
	ptyUInfo := lengthPrefixed(apuData)
 | 
			
		||||
	ptyVInfo := lengthPrefixed(apvData)
 | 
			
		||||
 | 
			
		||||
	// suppPubInfo is the encoded length of the output size in bits
 | 
			
		||||
	supPubInfo := make([]byte, 4)
 | 
			
		||||
	binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8)
 | 
			
		||||
 | 
			
		||||
	if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) {
 | 
			
		||||
		panic("public key not on same curve as private key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	z, _ := priv.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes())
 | 
			
		||||
	zBytes := z.Bytes()
 | 
			
		||||
 | 
			
		||||
	// Note that calling z.Bytes() on a big.Int may strip leading zero bytes from
 | 
			
		||||
	// the returned byte array. This can lead to a problem where zBytes will be
 | 
			
		||||
	// shorter than expected which breaks the key derivation. Therefore we must pad
 | 
			
		||||
	// to the full length of the expected coordinate here before calling the KDF.
 | 
			
		||||
	octSize := dSize(priv.Curve)
 | 
			
		||||
	if len(zBytes) != octSize {
 | 
			
		||||
		zBytes = append(bytes.Repeat([]byte{0}, octSize-len(zBytes)), zBytes...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reader := NewConcatKDF(crypto.SHA256, zBytes, algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{})
 | 
			
		||||
	key := make([]byte, size)
 | 
			
		||||
 | 
			
		||||
	// Read on the KDF will never fail
 | 
			
		||||
	_, _ = reader.Read(key)
 | 
			
		||||
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dSize returns the size in octets for a coordinate on a elliptic curve.
 | 
			
		||||
func dSize(curve elliptic.Curve) int {
 | 
			
		||||
	order := curve.Params().P
 | 
			
		||||
	bitLen := order.BitLen()
 | 
			
		||||
	size := bitLen / 8
 | 
			
		||||
	if bitLen%8 != 0 {
 | 
			
		||||
		size++
 | 
			
		||||
	}
 | 
			
		||||
	return size
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lengthPrefixed(data []byte) []byte {
 | 
			
		||||
	out := make([]byte, len(data)+4)
 | 
			
		||||
	binary.BigEndian.PutUint32(out, uint32(len(data)))
 | 
			
		||||
	copy(out[4:], data)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										109
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/key_wrap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/cipher/key_wrap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package josecipher
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/cipher"
 | 
			
		||||
	"crypto/subtle"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}
 | 
			
		||||
 | 
			
		||||
// KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher.
 | 
			
		||||
func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
 | 
			
		||||
	if len(cek)%8 != 0 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	n := len(cek) / 8
 | 
			
		||||
	r := make([][]byte, n)
 | 
			
		||||
 | 
			
		||||
	for i := range r {
 | 
			
		||||
		r[i] = make([]byte, 8)
 | 
			
		||||
		copy(r[i], cek[i*8:])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buffer := make([]byte, 16)
 | 
			
		||||
	tBytes := make([]byte, 8)
 | 
			
		||||
	copy(buffer, defaultIV)
 | 
			
		||||
 | 
			
		||||
	for t := 0; t < 6*n; t++ {
 | 
			
		||||
		copy(buffer[8:], r[t%n])
 | 
			
		||||
 | 
			
		||||
		block.Encrypt(buffer, buffer)
 | 
			
		||||
 | 
			
		||||
		binary.BigEndian.PutUint64(tBytes, uint64(t+1))
 | 
			
		||||
 | 
			
		||||
		for i := 0; i < 8; i++ {
 | 
			
		||||
			buffer[i] = buffer[i] ^ tBytes[i]
 | 
			
		||||
		}
 | 
			
		||||
		copy(r[t%n], buffer[8:])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out := make([]byte, (n+1)*8)
 | 
			
		||||
	copy(out, buffer[:8])
 | 
			
		||||
	for i := range r {
 | 
			
		||||
		copy(out[(i+1)*8:], r[i])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher.
 | 
			
		||||
func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
 | 
			
		||||
	if len(ciphertext)%8 != 0 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	n := (len(ciphertext) / 8) - 1
 | 
			
		||||
	r := make([][]byte, n)
 | 
			
		||||
 | 
			
		||||
	for i := range r {
 | 
			
		||||
		r[i] = make([]byte, 8)
 | 
			
		||||
		copy(r[i], ciphertext[(i+1)*8:])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buffer := make([]byte, 16)
 | 
			
		||||
	tBytes := make([]byte, 8)
 | 
			
		||||
	copy(buffer[:8], ciphertext[:8])
 | 
			
		||||
 | 
			
		||||
	for t := 6*n - 1; t >= 0; t-- {
 | 
			
		||||
		binary.BigEndian.PutUint64(tBytes, uint64(t+1))
 | 
			
		||||
 | 
			
		||||
		for i := 0; i < 8; i++ {
 | 
			
		||||
			buffer[i] = buffer[i] ^ tBytes[i]
 | 
			
		||||
		}
 | 
			
		||||
		copy(buffer[8:], r[t%n])
 | 
			
		||||
 | 
			
		||||
		block.Decrypt(buffer, buffer)
 | 
			
		||||
 | 
			
		||||
		copy(r[t%n], buffer[8:])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: failed to unwrap key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out := make([]byte, n*8)
 | 
			
		||||
	for i := range r {
 | 
			
		||||
		copy(out[i*8:], r[i])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										548
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/crypter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										548
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/crypter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,548 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/ecdsa"
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Encrypter represents an encrypter which produces an encrypted JWE object.
 | 
			
		||||
type Encrypter interface {
 | 
			
		||||
	Encrypt(plaintext []byte) (*JSONWebEncryption, error)
 | 
			
		||||
	EncryptWithAuthData(plaintext []byte, aad []byte) (*JSONWebEncryption, error)
 | 
			
		||||
	Options() EncrypterOptions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A generic content cipher
 | 
			
		||||
type contentCipher interface {
 | 
			
		||||
	keySize() int
 | 
			
		||||
	encrypt(cek []byte, aad, plaintext []byte) (*aeadParts, error)
 | 
			
		||||
	decrypt(cek []byte, aad []byte, parts *aeadParts) ([]byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A key generator (for generating/getting a CEK)
 | 
			
		||||
type keyGenerator interface {
 | 
			
		||||
	keySize() int
 | 
			
		||||
	genKey() ([]byte, rawHeader, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A generic key encrypter
 | 
			
		||||
type keyEncrypter interface {
 | 
			
		||||
	encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) // Encrypt a key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A generic key decrypter
 | 
			
		||||
type keyDecrypter interface {
 | 
			
		||||
	decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) // Decrypt a key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A generic encrypter based on the given key encrypter and content cipher.
 | 
			
		||||
type genericEncrypter struct {
 | 
			
		||||
	contentAlg     ContentEncryption
 | 
			
		||||
	compressionAlg CompressionAlgorithm
 | 
			
		||||
	cipher         contentCipher
 | 
			
		||||
	recipients     []recipientKeyInfo
 | 
			
		||||
	keyGenerator   keyGenerator
 | 
			
		||||
	extraHeaders   map[HeaderKey]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type recipientKeyInfo struct {
 | 
			
		||||
	keyID        string
 | 
			
		||||
	keyAlg       KeyAlgorithm
 | 
			
		||||
	keyEncrypter keyEncrypter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncrypterOptions represents options that can be set on new encrypters.
 | 
			
		||||
type EncrypterOptions struct {
 | 
			
		||||
	Compression CompressionAlgorithm
 | 
			
		||||
 | 
			
		||||
	// Optional map of additional keys to be inserted into the protected header
 | 
			
		||||
	// of a JWS object. Some specifications which make use of JWS like to insert
 | 
			
		||||
	// additional values here. All values must be JSON-serializable.
 | 
			
		||||
	ExtraHeaders map[HeaderKey]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
 | 
			
		||||
// if necessary. It returns itself and so can be used in a fluent style.
 | 
			
		||||
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
 | 
			
		||||
	if eo.ExtraHeaders == nil {
 | 
			
		||||
		eo.ExtraHeaders = map[HeaderKey]interface{}{}
 | 
			
		||||
	}
 | 
			
		||||
	eo.ExtraHeaders[k] = v
 | 
			
		||||
	return eo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithContentType adds a content type ("cty") header and returns the updated
 | 
			
		||||
// EncrypterOptions.
 | 
			
		||||
func (eo *EncrypterOptions) WithContentType(contentType ContentType) *EncrypterOptions {
 | 
			
		||||
	return eo.WithHeader(HeaderContentType, contentType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithType adds a type ("typ") header and returns the updated EncrypterOptions.
 | 
			
		||||
func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions {
 | 
			
		||||
	return eo.WithHeader(HeaderType, typ)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Recipient represents an algorithm/key to encrypt messages to.
 | 
			
		||||
//
 | 
			
		||||
// PBES2Count and PBES2Salt correspond with the  "p2c" and "p2s" headers used
 | 
			
		||||
// on the password-based encryption algorithms PBES2-HS256+A128KW,
 | 
			
		||||
// PBES2-HS384+A192KW, and PBES2-HS512+A256KW. If they are not provided a safe
 | 
			
		||||
// default of 100000 will be used for the count and a 128-bit random salt will
 | 
			
		||||
// be generated.
 | 
			
		||||
type Recipient struct {
 | 
			
		||||
	Algorithm  KeyAlgorithm
 | 
			
		||||
	Key        interface{}
 | 
			
		||||
	KeyID      string
 | 
			
		||||
	PBES2Count int
 | 
			
		||||
	PBES2Salt  []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewEncrypter creates an appropriate encrypter based on the key type
 | 
			
		||||
func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions) (Encrypter, error) {
 | 
			
		||||
	encrypter := &genericEncrypter{
 | 
			
		||||
		contentAlg: enc,
 | 
			
		||||
		recipients: []recipientKeyInfo{},
 | 
			
		||||
		cipher:     getContentCipher(enc),
 | 
			
		||||
	}
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		encrypter.compressionAlg = opts.Compression
 | 
			
		||||
		encrypter.extraHeaders = opts.ExtraHeaders
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if encrypter.cipher == nil {
 | 
			
		||||
		return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var keyID string
 | 
			
		||||
	var rawKey interface{}
 | 
			
		||||
	switch encryptionKey := rcpt.Key.(type) {
 | 
			
		||||
	case JSONWebKey:
 | 
			
		||||
		keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key
 | 
			
		||||
	case *JSONWebKey:
 | 
			
		||||
		keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key
 | 
			
		||||
	case OpaqueKeyEncrypter:
 | 
			
		||||
		keyID, rawKey = encryptionKey.KeyID(), encryptionKey
 | 
			
		||||
	default:
 | 
			
		||||
		rawKey = encryptionKey
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch rcpt.Algorithm {
 | 
			
		||||
	case DIRECT:
 | 
			
		||||
		// Direct encryption mode must be treated differently
 | 
			
		||||
		if reflect.TypeOf(rawKey) != reflect.TypeOf([]byte{}) {
 | 
			
		||||
			return nil, ErrUnsupportedKeyType
 | 
			
		||||
		}
 | 
			
		||||
		if encrypter.cipher.keySize() != len(rawKey.([]byte)) {
 | 
			
		||||
			return nil, ErrInvalidKeySize
 | 
			
		||||
		}
 | 
			
		||||
		encrypter.keyGenerator = staticKeyGenerator{
 | 
			
		||||
			key: rawKey.([]byte),
 | 
			
		||||
		}
 | 
			
		||||
		recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, rawKey.([]byte))
 | 
			
		||||
		recipientInfo.keyID = keyID
 | 
			
		||||
		if rcpt.KeyID != "" {
 | 
			
		||||
			recipientInfo.keyID = rcpt.KeyID
 | 
			
		||||
		}
 | 
			
		||||
		encrypter.recipients = []recipientKeyInfo{recipientInfo}
 | 
			
		||||
		return encrypter, nil
 | 
			
		||||
	case ECDH_ES:
 | 
			
		||||
		// ECDH-ES (w/o key wrapping) is similar to DIRECT mode
 | 
			
		||||
		typeOf := reflect.TypeOf(rawKey)
 | 
			
		||||
		if typeOf != reflect.TypeOf(&ecdsa.PublicKey{}) {
 | 
			
		||||
			return nil, ErrUnsupportedKeyType
 | 
			
		||||
		}
 | 
			
		||||
		encrypter.keyGenerator = ecKeyGenerator{
 | 
			
		||||
			size:      encrypter.cipher.keySize(),
 | 
			
		||||
			algID:     string(enc),
 | 
			
		||||
			publicKey: rawKey.(*ecdsa.PublicKey),
 | 
			
		||||
		}
 | 
			
		||||
		recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, rawKey.(*ecdsa.PublicKey))
 | 
			
		||||
		recipientInfo.keyID = keyID
 | 
			
		||||
		if rcpt.KeyID != "" {
 | 
			
		||||
			recipientInfo.keyID = rcpt.KeyID
 | 
			
		||||
		}
 | 
			
		||||
		encrypter.recipients = []recipientKeyInfo{recipientInfo}
 | 
			
		||||
		return encrypter, nil
 | 
			
		||||
	default:
 | 
			
		||||
		// Can just add a standard recipient
 | 
			
		||||
		encrypter.keyGenerator = randomKeyGenerator{
 | 
			
		||||
			size: encrypter.cipher.keySize(),
 | 
			
		||||
		}
 | 
			
		||||
		err := encrypter.addRecipient(rcpt)
 | 
			
		||||
		return encrypter, err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMultiEncrypter creates a multi-encrypter based on the given parameters
 | 
			
		||||
func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *EncrypterOptions) (Encrypter, error) {
 | 
			
		||||
	cipher := getContentCipher(enc)
 | 
			
		||||
 | 
			
		||||
	if cipher == nil {
 | 
			
		||||
		return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
	if rcpts == nil || len(rcpts) == 0 {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: recipients is nil or empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	encrypter := &genericEncrypter{
 | 
			
		||||
		contentAlg: enc,
 | 
			
		||||
		recipients: []recipientKeyInfo{},
 | 
			
		||||
		cipher:     cipher,
 | 
			
		||||
		keyGenerator: randomKeyGenerator{
 | 
			
		||||
			size: cipher.keySize(),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		encrypter.compressionAlg = opts.Compression
 | 
			
		||||
		encrypter.extraHeaders = opts.ExtraHeaders
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, recipient := range rcpts {
 | 
			
		||||
		err := encrypter.addRecipient(recipient)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return encrypter, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) {
 | 
			
		||||
	var recipientInfo recipientKeyInfo
 | 
			
		||||
 | 
			
		||||
	switch recipient.Algorithm {
 | 
			
		||||
	case DIRECT, ECDH_ES:
 | 
			
		||||
		return fmt.Errorf("go-jose/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key)
 | 
			
		||||
	if recipient.KeyID != "" {
 | 
			
		||||
		recipientInfo.keyID = recipient.KeyID
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch recipient.Algorithm {
 | 
			
		||||
	case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
 | 
			
		||||
		if sr, ok := recipientInfo.keyEncrypter.(*symmetricKeyCipher); ok {
 | 
			
		||||
			sr.p2c = recipient.PBES2Count
 | 
			
		||||
			sr.p2s = recipient.PBES2Salt
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		ctx.recipients = append(ctx.recipients, recipientInfo)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKeyInfo, error) {
 | 
			
		||||
	switch encryptionKey := encryptionKey.(type) {
 | 
			
		||||
	case *rsa.PublicKey:
 | 
			
		||||
		return newRSARecipient(alg, encryptionKey)
 | 
			
		||||
	case *ecdsa.PublicKey:
 | 
			
		||||
		return newECDHRecipient(alg, encryptionKey)
 | 
			
		||||
	case []byte:
 | 
			
		||||
		return newSymmetricRecipient(alg, encryptionKey)
 | 
			
		||||
	case string:
 | 
			
		||||
		return newSymmetricRecipient(alg, []byte(encryptionKey))
 | 
			
		||||
	case *JSONWebKey:
 | 
			
		||||
		recipient, err := makeJWERecipient(alg, encryptionKey.Key)
 | 
			
		||||
		recipient.keyID = encryptionKey.KeyID
 | 
			
		||||
		return recipient, err
 | 
			
		||||
	}
 | 
			
		||||
	if encrypter, ok := encryptionKey.(OpaqueKeyEncrypter); ok {
 | 
			
		||||
		return newOpaqueKeyEncrypter(alg, encrypter)
 | 
			
		||||
	}
 | 
			
		||||
	return recipientKeyInfo{}, ErrUnsupportedKeyType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newDecrypter creates an appropriate decrypter based on the key type
 | 
			
		||||
func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) {
 | 
			
		||||
	switch decryptionKey := decryptionKey.(type) {
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
		return &rsaDecrypterSigner{
 | 
			
		||||
			privateKey: decryptionKey,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
		return &ecDecrypterSigner{
 | 
			
		||||
			privateKey: decryptionKey,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case []byte:
 | 
			
		||||
		return &symmetricKeyCipher{
 | 
			
		||||
			key: decryptionKey,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case string:
 | 
			
		||||
		return &symmetricKeyCipher{
 | 
			
		||||
			key: []byte(decryptionKey),
 | 
			
		||||
		}, nil
 | 
			
		||||
	case JSONWebKey:
 | 
			
		||||
		return newDecrypter(decryptionKey.Key)
 | 
			
		||||
	case *JSONWebKey:
 | 
			
		||||
		return newDecrypter(decryptionKey.Key)
 | 
			
		||||
	}
 | 
			
		||||
	if okd, ok := decryptionKey.(OpaqueKeyDecrypter); ok {
 | 
			
		||||
		return &opaqueKeyDecrypter{decrypter: okd}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, ErrUnsupportedKeyType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implementation of encrypt method producing a JWE object.
 | 
			
		||||
func (ctx *genericEncrypter) Encrypt(plaintext []byte) (*JSONWebEncryption, error) {
 | 
			
		||||
	return ctx.EncryptWithAuthData(plaintext, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implementation of encrypt method producing a JWE object.
 | 
			
		||||
func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWebEncryption, error) {
 | 
			
		||||
	obj := &JSONWebEncryption{}
 | 
			
		||||
	obj.aad = aad
 | 
			
		||||
 | 
			
		||||
	obj.protected = &rawHeader{}
 | 
			
		||||
	err := obj.protected.set(headerEncryption, ctx.contentAlg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obj.recipients = make([]recipientInfo, len(ctx.recipients))
 | 
			
		||||
 | 
			
		||||
	if len(ctx.recipients) == 0 {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: no recipients to encrypt to")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cek, headers, err := ctx.keyGenerator.genKey()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obj.protected.merge(&headers)
 | 
			
		||||
 | 
			
		||||
	for i, info := range ctx.recipients {
 | 
			
		||||
		recipient, err := info.keyEncrypter.encryptKey(cek, info.keyAlg)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = recipient.header.set(headerAlgorithm, info.keyAlg)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if info.keyID != "" {
 | 
			
		||||
			err = recipient.header.set(headerKeyID, info.keyID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		obj.recipients[i] = recipient
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ctx.recipients) == 1 {
 | 
			
		||||
		// Move per-recipient headers into main protected header if there's
 | 
			
		||||
		// only a single recipient.
 | 
			
		||||
		obj.protected.merge(obj.recipients[0].header)
 | 
			
		||||
		obj.recipients[0].header = nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ctx.compressionAlg != NONE {
 | 
			
		||||
		plaintext, err = compress(ctx.compressionAlg, plaintext)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = obj.protected.set(headerCompression, ctx.compressionAlg)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for k, v := range ctx.extraHeaders {
 | 
			
		||||
		b, err := json.Marshal(v)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		(*obj.protected)[k] = makeRawMessage(b)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	authData := obj.computeAuthData()
 | 
			
		||||
	parts, err := ctx.cipher.encrypt(cek, authData, plaintext)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obj.iv = parts.iv
 | 
			
		||||
	obj.ciphertext = parts.ciphertext
 | 
			
		||||
	obj.tag = parts.tag
 | 
			
		||||
 | 
			
		||||
	return obj, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *genericEncrypter) Options() EncrypterOptions {
 | 
			
		||||
	return EncrypterOptions{
 | 
			
		||||
		Compression:  ctx.compressionAlg,
 | 
			
		||||
		ExtraHeaders: ctx.extraHeaders,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decrypt and validate the object and return the plaintext. Note that this
 | 
			
		||||
// function does not support multi-recipient, if you desire multi-recipient
 | 
			
		||||
// decryption use DecryptMulti instead.
 | 
			
		||||
//
 | 
			
		||||
// Automatically decompresses plaintext, but returns an error if the decompressed
 | 
			
		||||
// data would be >250kB or >10x the size of the compressed data, whichever is larger.
 | 
			
		||||
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
 | 
			
		||||
	headers := obj.mergedHeaders(nil)
 | 
			
		||||
 | 
			
		||||
	if len(obj.recipients) > 1 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	critical, err := headers.getCritical()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(critical) > 0 {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	decrypter, err := newDecrypter(decryptionKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cipher := getContentCipher(headers.getEncryption())
 | 
			
		||||
	if cipher == nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(headers.getEncryption()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	generator := randomKeyGenerator{
 | 
			
		||||
		size: cipher.keySize(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parts := &aeadParts{
 | 
			
		||||
		iv:         obj.iv,
 | 
			
		||||
		ciphertext: obj.ciphertext,
 | 
			
		||||
		tag:        obj.tag,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	authData := obj.computeAuthData()
 | 
			
		||||
 | 
			
		||||
	var plaintext []byte
 | 
			
		||||
	recipient := obj.recipients[0]
 | 
			
		||||
	recipientHeaders := obj.mergedHeaders(&recipient)
 | 
			
		||||
 | 
			
		||||
	cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		// Found a valid CEK -- let's try to decrypt.
 | 
			
		||||
		plaintext, err = cipher.decrypt(cek, authData, parts)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if plaintext == nil {
 | 
			
		||||
		return nil, ErrCryptoFailure
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The "zip" header parameter may only be present in the protected header.
 | 
			
		||||
	if comp := obj.protected.getCompression(); comp != "" {
 | 
			
		||||
		plaintext, err = decompress(comp, plaintext)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return plaintext, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecryptMulti decrypts and validates the object and returns the plaintexts,
 | 
			
		||||
// with support for multiple recipients. It returns the index of the recipient
 | 
			
		||||
// for which the decryption was successful, the merged headers for that recipient,
 | 
			
		||||
// and the plaintext.
 | 
			
		||||
//
 | 
			
		||||
// Automatically decompresses plaintext, but returns an error if the decompressed
 | 
			
		||||
// data would be >250kB or >3x the size of the compressed data, whichever is larger.
 | 
			
		||||
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
 | 
			
		||||
	globalHeaders := obj.mergedHeaders(nil)
 | 
			
		||||
 | 
			
		||||
	critical, err := globalHeaders.getCritical()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(critical) > 0 {
 | 
			
		||||
		return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	decrypter, err := newDecrypter(decryptionKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, Header{}, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	encryption := globalHeaders.getEncryption()
 | 
			
		||||
	cipher := getContentCipher(encryption)
 | 
			
		||||
	if cipher == nil {
 | 
			
		||||
		return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(encryption))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	generator := randomKeyGenerator{
 | 
			
		||||
		size: cipher.keySize(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parts := &aeadParts{
 | 
			
		||||
		iv:         obj.iv,
 | 
			
		||||
		ciphertext: obj.ciphertext,
 | 
			
		||||
		tag:        obj.tag,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	authData := obj.computeAuthData()
 | 
			
		||||
 | 
			
		||||
	index := -1
 | 
			
		||||
	var plaintext []byte
 | 
			
		||||
	var headers rawHeader
 | 
			
		||||
 | 
			
		||||
	for i, recipient := range obj.recipients {
 | 
			
		||||
		recipientHeaders := obj.mergedHeaders(&recipient)
 | 
			
		||||
 | 
			
		||||
		cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			// Found a valid CEK -- let's try to decrypt.
 | 
			
		||||
			plaintext, err = cipher.decrypt(cek, authData, parts)
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				index = i
 | 
			
		||||
				headers = recipientHeaders
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if plaintext == nil || err != nil {
 | 
			
		||||
		return -1, Header{}, nil, ErrCryptoFailure
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The "zip" header parameter may only be present in the protected header.
 | 
			
		||||
	if comp := obj.protected.getCompression(); comp != "" {
 | 
			
		||||
		plaintext, err = decompress(comp, plaintext)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sanitized, err := headers.sanitized()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to sanitize header: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return index, sanitized, plaintext, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
Package jose aims to provide an implementation of the Javascript Object Signing
 | 
			
		||||
and Encryption set of standards. It implements encryption and signing based on
 | 
			
		||||
the JSON Web Encryption and JSON Web Signature standards, with optional JSON
 | 
			
		||||
Web Token support available in a sub-package. The library supports both the
 | 
			
		||||
compact and full serialization formats, and has optional support for multiple
 | 
			
		||||
recipients.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
package jose
 | 
			
		||||
							
								
								
									
										198
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/encoding.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/encoding.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,198 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"compress/flate"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Helper function to serialize known-good objects.
 | 
			
		||||
// Precondition: value is not a nil pointer.
 | 
			
		||||
func mustSerializeJSON(value interface{}) []byte {
 | 
			
		||||
	out, err := json.Marshal(value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	// We never want to serialize the top-level value "null," since it's not a
 | 
			
		||||
	// valid JOSE message. But if a caller passes in a nil pointer to this method,
 | 
			
		||||
	// MarshalJSON will happily serialize it as the top-level value "null". If
 | 
			
		||||
	// that value is then embedded in another operation, for instance by being
 | 
			
		||||
	// base64-encoded and fed as input to a signing algorithm
 | 
			
		||||
	// (https://github.com/go-jose/go-jose/issues/22), the result will be
 | 
			
		||||
	// incorrect. Because this method is intended for known-good objects, and a nil
 | 
			
		||||
	// pointer is not a known-good object, we are free to panic in this case.
 | 
			
		||||
	// Note: It's not possible to directly check whether the data pointed at by an
 | 
			
		||||
	// interface is a nil pointer, so we do this hacky workaround.
 | 
			
		||||
	// https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I
 | 
			
		||||
	if string(out) == "null" {
 | 
			
		||||
		panic("Tried to serialize a nil pointer.")
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Strip all newlines and whitespace
 | 
			
		||||
func stripWhitespace(data string) string {
 | 
			
		||||
	buf := strings.Builder{}
 | 
			
		||||
	buf.Grow(len(data))
 | 
			
		||||
	for _, r := range data {
 | 
			
		||||
		if !unicode.IsSpace(r) {
 | 
			
		||||
			buf.WriteRune(r)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Perform compression based on algorithm
 | 
			
		||||
func compress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
 | 
			
		||||
	switch algorithm {
 | 
			
		||||
	case DEFLATE:
 | 
			
		||||
		return deflate(input)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Perform decompression based on algorithm
 | 
			
		||||
func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
 | 
			
		||||
	switch algorithm {
 | 
			
		||||
	case DEFLATE:
 | 
			
		||||
		return inflate(input)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// deflate compresses the input.
 | 
			
		||||
func deflate(input []byte) ([]byte, error) {
 | 
			
		||||
	output := new(bytes.Buffer)
 | 
			
		||||
 | 
			
		||||
	// Writing to byte buffer, err is always nil
 | 
			
		||||
	writer, _ := flate.NewWriter(output, 1)
 | 
			
		||||
	_, _ = io.Copy(writer, bytes.NewBuffer(input))
 | 
			
		||||
 | 
			
		||||
	err := writer.Close()
 | 
			
		||||
	return output.Bytes(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// inflate decompresses the input.
 | 
			
		||||
//
 | 
			
		||||
// Errors if the decompressed data would be >250kB or >10x the size of the
 | 
			
		||||
// compressed data, whichever is larger.
 | 
			
		||||
func inflate(input []byte) ([]byte, error) {
 | 
			
		||||
	output := new(bytes.Buffer)
 | 
			
		||||
	reader := flate.NewReader(bytes.NewBuffer(input))
 | 
			
		||||
 | 
			
		||||
	maxCompressedSize := 10 * int64(len(input))
 | 
			
		||||
	if maxCompressedSize < 250000 {
 | 
			
		||||
		maxCompressedSize = 250000
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	limit := maxCompressedSize + 1
 | 
			
		||||
	n, err := io.CopyN(output, reader, limit)
 | 
			
		||||
	if err != nil && err != io.EOF {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if n == limit {
 | 
			
		||||
		return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = reader.Close()
 | 
			
		||||
	return output.Bytes(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// byteBuffer represents a slice of bytes that can be serialized to url-safe base64.
 | 
			
		||||
type byteBuffer struct {
 | 
			
		||||
	data []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newBuffer(data []byte) *byteBuffer {
 | 
			
		||||
	if data == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return &byteBuffer{
 | 
			
		||||
		data: data,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newFixedSizeBuffer(data []byte, length int) *byteBuffer {
 | 
			
		||||
	if len(data) > length {
 | 
			
		||||
		panic("go-jose/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)")
 | 
			
		||||
	}
 | 
			
		||||
	pad := make([]byte, length-len(data))
 | 
			
		||||
	return newBuffer(append(pad, data...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newBufferFromInt(num uint64) *byteBuffer {
 | 
			
		||||
	data := make([]byte, 8)
 | 
			
		||||
	binary.BigEndian.PutUint64(data, num)
 | 
			
		||||
	return newBuffer(bytes.TrimLeft(data, "\x00"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *byteBuffer) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return json.Marshal(b.base64())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 := base64.RawURLEncoding.DecodeString(encoded)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*b = *newBuffer(decoded)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *byteBuffer) base64() string {
 | 
			
		||||
	return base64.RawURLEncoding.EncodeToString(b.data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *byteBuffer) bytes() []byte {
 | 
			
		||||
	// Handling nil here allows us to transparently handle nil slices when serializing.
 | 
			
		||||
	if b == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return b.data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b byteBuffer) bigInt() *big.Int {
 | 
			
		||||
	return new(big.Int).SetBytes(b.data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b byteBuffer) toInt() int {
 | 
			
		||||
	return int(b.bigInt().Int64())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
Copyright (c) 2012 The Go Authors. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are
 | 
			
		||||
met:
 | 
			
		||||
 | 
			
		||||
   * Redistributions of source code must retain the above copyright
 | 
			
		||||
notice, this list of conditions and the following disclaimer.
 | 
			
		||||
   * Redistributions in binary form must reproduce the above
 | 
			
		||||
copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
in the documentation and/or other materials provided with the
 | 
			
		||||
distribution.
 | 
			
		||||
   * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
contributors may be used to endorse or promote products derived from
 | 
			
		||||
this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
# Safe JSON
 | 
			
		||||
 | 
			
		||||
This repository contains a fork of the `encoding/json` package from Go 1.6.
 | 
			
		||||
 | 
			
		||||
The following changes were made:
 | 
			
		||||
 | 
			
		||||
* Object deserialization uses case-sensitive member name matching instead of
 | 
			
		||||
  [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html).
 | 
			
		||||
  This is to avoid differences in the interpretation of JOSE messages between
 | 
			
		||||
  go-jose and libraries written in other languages.
 | 
			
		||||
* When deserializing a JSON object, we check for duplicate keys and reject the
 | 
			
		||||
  input whenever we detect a duplicate. Rather than trying to work with malformed
 | 
			
		||||
  data, we prefer to reject it right away.
 | 
			
		||||
							
								
								
									
										1217
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1217
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1197
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/encode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1197
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/encode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										141
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/indent.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/indent.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
// Copyright 2010 The Go 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 json
 | 
			
		||||
 | 
			
		||||
import "bytes"
 | 
			
		||||
 | 
			
		||||
// Compact appends to dst the JSON-encoded src with
 | 
			
		||||
// insignificant space characters elided.
 | 
			
		||||
func Compact(dst *bytes.Buffer, src []byte) error {
 | 
			
		||||
	return compact(dst, src, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func compact(dst *bytes.Buffer, src []byte, escape bool) error {
 | 
			
		||||
	origLen := dst.Len()
 | 
			
		||||
	var scan scanner
 | 
			
		||||
	scan.reset()
 | 
			
		||||
	start := 0
 | 
			
		||||
	for i, c := range src {
 | 
			
		||||
		if escape && (c == '<' || c == '>' || c == '&') {
 | 
			
		||||
			if start < i {
 | 
			
		||||
				dst.Write(src[start:i])
 | 
			
		||||
			}
 | 
			
		||||
			dst.WriteString(`\u00`)
 | 
			
		||||
			dst.WriteByte(hex[c>>4])
 | 
			
		||||
			dst.WriteByte(hex[c&0xF])
 | 
			
		||||
			start = i + 1
 | 
			
		||||
		}
 | 
			
		||||
		// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
 | 
			
		||||
		if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
 | 
			
		||||
			if start < i {
 | 
			
		||||
				dst.Write(src[start:i])
 | 
			
		||||
			}
 | 
			
		||||
			dst.WriteString(`\u202`)
 | 
			
		||||
			dst.WriteByte(hex[src[i+2]&0xF])
 | 
			
		||||
			start = i + 3
 | 
			
		||||
		}
 | 
			
		||||
		v := scan.step(&scan, c)
 | 
			
		||||
		if v >= scanSkipSpace {
 | 
			
		||||
			if v == scanError {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			if start < i {
 | 
			
		||||
				dst.Write(src[start:i])
 | 
			
		||||
			}
 | 
			
		||||
			start = i + 1
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if scan.eof() == scanError {
 | 
			
		||||
		dst.Truncate(origLen)
 | 
			
		||||
		return scan.err
 | 
			
		||||
	}
 | 
			
		||||
	if start < len(src) {
 | 
			
		||||
		dst.Write(src[start:])
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
 | 
			
		||||
	dst.WriteByte('\n')
 | 
			
		||||
	dst.WriteString(prefix)
 | 
			
		||||
	for i := 0; i < depth; i++ {
 | 
			
		||||
		dst.WriteString(indent)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Indent appends to dst an indented form of the JSON-encoded src.
 | 
			
		||||
// Each element in a JSON object or array begins on a new,
 | 
			
		||||
// indented line beginning with prefix followed by one or more
 | 
			
		||||
// copies of indent according to the indentation nesting.
 | 
			
		||||
// The data appended to dst does not begin with the prefix nor
 | 
			
		||||
// any indentation, to make it easier to embed inside other formatted JSON data.
 | 
			
		||||
// Although leading space characters (space, tab, carriage return, newline)
 | 
			
		||||
// at the beginning of src are dropped, trailing space characters
 | 
			
		||||
// at the end of src are preserved and copied to dst.
 | 
			
		||||
// For example, if src has no trailing spaces, neither will dst;
 | 
			
		||||
// if src ends in a trailing newline, so will dst.
 | 
			
		||||
func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
 | 
			
		||||
	origLen := dst.Len()
 | 
			
		||||
	var scan scanner
 | 
			
		||||
	scan.reset()
 | 
			
		||||
	needIndent := false
 | 
			
		||||
	depth := 0
 | 
			
		||||
	for _, c := range src {
 | 
			
		||||
		scan.bytes++
 | 
			
		||||
		v := scan.step(&scan, c)
 | 
			
		||||
		if v == scanSkipSpace {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if v == scanError {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if needIndent && v != scanEndObject && v != scanEndArray {
 | 
			
		||||
			needIndent = false
 | 
			
		||||
			depth++
 | 
			
		||||
			newline(dst, prefix, indent, depth)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Emit semantically uninteresting bytes
 | 
			
		||||
		// (in particular, punctuation in strings) unmodified.
 | 
			
		||||
		if v == scanContinue {
 | 
			
		||||
			dst.WriteByte(c)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Add spacing around real punctuation.
 | 
			
		||||
		switch c {
 | 
			
		||||
		case '{', '[':
 | 
			
		||||
			// delay indent so that empty object and array are formatted as {} and [].
 | 
			
		||||
			needIndent = true
 | 
			
		||||
			dst.WriteByte(c)
 | 
			
		||||
 | 
			
		||||
		case ',':
 | 
			
		||||
			dst.WriteByte(c)
 | 
			
		||||
			newline(dst, prefix, indent, depth)
 | 
			
		||||
 | 
			
		||||
		case ':':
 | 
			
		||||
			dst.WriteByte(c)
 | 
			
		||||
			dst.WriteByte(' ')
 | 
			
		||||
 | 
			
		||||
		case '}', ']':
 | 
			
		||||
			if needIndent {
 | 
			
		||||
				// suppress indent in empty object/array
 | 
			
		||||
				needIndent = false
 | 
			
		||||
			} else {
 | 
			
		||||
				depth--
 | 
			
		||||
				newline(dst, prefix, indent, depth)
 | 
			
		||||
			}
 | 
			
		||||
			dst.WriteByte(c)
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			dst.WriteByte(c)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if scan.eof() == scanError {
 | 
			
		||||
		dst.Truncate(origLen)
 | 
			
		||||
		return scan.err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										623
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										623
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,623 @@
 | 
			
		||||
// Copyright 2010 The Go 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 json
 | 
			
		||||
 | 
			
		||||
// JSON value parser state machine.
 | 
			
		||||
// Just about at the limit of what is reasonable to write by hand.
 | 
			
		||||
// Some parts are a bit tedious, but overall it nicely factors out the
 | 
			
		||||
// otherwise common code from the multiple scanning functions
 | 
			
		||||
// in this package (Compact, Indent, checkValid, nextValue, etc).
 | 
			
		||||
//
 | 
			
		||||
// This file starts with two simple examples using the scanner
 | 
			
		||||
// before diving into the scanner itself.
 | 
			
		||||
 | 
			
		||||
import "strconv"
 | 
			
		||||
 | 
			
		||||
// checkValid verifies that data is valid JSON-encoded data.
 | 
			
		||||
// scan is passed in for use by checkValid to avoid an allocation.
 | 
			
		||||
func checkValid(data []byte, scan *scanner) error {
 | 
			
		||||
	scan.reset()
 | 
			
		||||
	for _, c := range data {
 | 
			
		||||
		scan.bytes++
 | 
			
		||||
		if scan.step(scan, c) == scanError {
 | 
			
		||||
			return scan.err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if scan.eof() == scanError {
 | 
			
		||||
		return scan.err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nextValue splits data after the next whole JSON value,
 | 
			
		||||
// returning that value and the bytes that follow it as separate slices.
 | 
			
		||||
// scan is passed in for use by nextValue to avoid an allocation.
 | 
			
		||||
func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
 | 
			
		||||
	scan.reset()
 | 
			
		||||
	for i, c := range data {
 | 
			
		||||
		v := scan.step(scan, c)
 | 
			
		||||
		if v >= scanEndObject {
 | 
			
		||||
			switch v {
 | 
			
		||||
			// probe the scanner with a space to determine whether we will
 | 
			
		||||
			// get scanEnd on the next character. Otherwise, if the next character
 | 
			
		||||
			// is not a space, scanEndTop allocates a needless error.
 | 
			
		||||
			case scanEndObject, scanEndArray:
 | 
			
		||||
				if scan.step(scan, ' ') == scanEnd {
 | 
			
		||||
					return data[:i+1], data[i+1:], nil
 | 
			
		||||
				}
 | 
			
		||||
			case scanError:
 | 
			
		||||
				return nil, nil, scan.err
 | 
			
		||||
			case scanEnd:
 | 
			
		||||
				return data[:i], data[i:], nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if scan.eof() == scanError {
 | 
			
		||||
		return nil, nil, scan.err
 | 
			
		||||
	}
 | 
			
		||||
	return data, nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A SyntaxError is a description of a JSON syntax error.
 | 
			
		||||
type SyntaxError struct {
 | 
			
		||||
	msg    string // description of error
 | 
			
		||||
	Offset int64  // error occurred after reading Offset bytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *SyntaxError) Error() string { return e.msg }
 | 
			
		||||
 | 
			
		||||
// A scanner is a JSON scanning state machine.
 | 
			
		||||
// Callers call scan.reset() and then pass bytes in one at a time
 | 
			
		||||
// by calling scan.step(&scan, c) for each byte.
 | 
			
		||||
// The return value, referred to as an opcode, tells the
 | 
			
		||||
// caller about significant parsing events like beginning
 | 
			
		||||
// and ending literals, objects, and arrays, so that the
 | 
			
		||||
// caller can follow along if it wishes.
 | 
			
		||||
// The return value scanEnd indicates that a single top-level
 | 
			
		||||
// JSON value has been completed, *before* the byte that
 | 
			
		||||
// just got passed in.  (The indication must be delayed in order
 | 
			
		||||
// to recognize the end of numbers: is 123 a whole value or
 | 
			
		||||
// the beginning of 12345e+6?).
 | 
			
		||||
type scanner struct {
 | 
			
		||||
	// The step is a func to be called to execute the next transition.
 | 
			
		||||
	// Also tried using an integer constant and a single func
 | 
			
		||||
	// with a switch, but using the func directly was 10% faster
 | 
			
		||||
	// on a 64-bit Mac Mini, and it's nicer to read.
 | 
			
		||||
	step func(*scanner, byte) int
 | 
			
		||||
 | 
			
		||||
	// Reached end of top-level value.
 | 
			
		||||
	endTop bool
 | 
			
		||||
 | 
			
		||||
	// Stack of what we're in the middle of - array values, object keys, object values.
 | 
			
		||||
	parseState []int
 | 
			
		||||
 | 
			
		||||
	// Error that happened, if any.
 | 
			
		||||
	err error
 | 
			
		||||
 | 
			
		||||
	// 1-byte redo (see undo method)
 | 
			
		||||
	redo      bool
 | 
			
		||||
	redoCode  int
 | 
			
		||||
	redoState func(*scanner, byte) int
 | 
			
		||||
 | 
			
		||||
	// total bytes consumed, updated by decoder.Decode
 | 
			
		||||
	bytes int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// These values are returned by the state transition functions
 | 
			
		||||
// assigned to scanner.state and the method scanner.eof.
 | 
			
		||||
// They give details about the current state of the scan that
 | 
			
		||||
// callers might be interested to know about.
 | 
			
		||||
// It is okay to ignore the return value of any particular
 | 
			
		||||
// call to scanner.state: if one call returns scanError,
 | 
			
		||||
// every subsequent call will return scanError too.
 | 
			
		||||
const (
 | 
			
		||||
	// Continue.
 | 
			
		||||
	scanContinue     = iota // uninteresting byte
 | 
			
		||||
	scanBeginLiteral        // end implied by next result != scanContinue
 | 
			
		||||
	scanBeginObject         // begin object
 | 
			
		||||
	scanObjectKey           // just finished object key (string)
 | 
			
		||||
	scanObjectValue         // just finished non-last object value
 | 
			
		||||
	scanEndObject           // end object (implies scanObjectValue if possible)
 | 
			
		||||
	scanBeginArray          // begin array
 | 
			
		||||
	scanArrayValue          // just finished array value
 | 
			
		||||
	scanEndArray            // end array (implies scanArrayValue if possible)
 | 
			
		||||
	scanSkipSpace           // space byte; can skip; known to be last "continue" result
 | 
			
		||||
 | 
			
		||||
	// Stop.
 | 
			
		||||
	scanEnd   // top-level value ended *before* this byte; known to be first "stop" result
 | 
			
		||||
	scanError // hit an error, scanner.err.
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// These values are stored in the parseState stack.
 | 
			
		||||
// They give the current state of a composite value
 | 
			
		||||
// being scanned.  If the parser is inside a nested value
 | 
			
		||||
// the parseState describes the nested state, outermost at entry 0.
 | 
			
		||||
const (
 | 
			
		||||
	parseObjectKey   = iota // parsing object key (before colon)
 | 
			
		||||
	parseObjectValue        // parsing object value (after colon)
 | 
			
		||||
	parseArrayValue         // parsing array value
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// reset prepares the scanner for use.
 | 
			
		||||
// It must be called before calling s.step.
 | 
			
		||||
func (s *scanner) reset() {
 | 
			
		||||
	s.step = stateBeginValue
 | 
			
		||||
	s.parseState = s.parseState[0:0]
 | 
			
		||||
	s.err = nil
 | 
			
		||||
	s.redo = false
 | 
			
		||||
	s.endTop = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// eof tells the scanner that the end of input has been reached.
 | 
			
		||||
// It returns a scan status just as s.step does.
 | 
			
		||||
func (s *scanner) eof() int {
 | 
			
		||||
	if s.err != nil {
 | 
			
		||||
		return scanError
 | 
			
		||||
	}
 | 
			
		||||
	if s.endTop {
 | 
			
		||||
		return scanEnd
 | 
			
		||||
	}
 | 
			
		||||
	s.step(s, ' ')
 | 
			
		||||
	if s.endTop {
 | 
			
		||||
		return scanEnd
 | 
			
		||||
	}
 | 
			
		||||
	if s.err == nil {
 | 
			
		||||
		s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
 | 
			
		||||
	}
 | 
			
		||||
	return scanError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// pushParseState pushes a new parse state p onto the parse stack.
 | 
			
		||||
func (s *scanner) pushParseState(p int) {
 | 
			
		||||
	s.parseState = append(s.parseState, p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// popParseState pops a parse state (already obtained) off the stack
 | 
			
		||||
// and updates s.step accordingly.
 | 
			
		||||
func (s *scanner) popParseState() {
 | 
			
		||||
	n := len(s.parseState) - 1
 | 
			
		||||
	s.parseState = s.parseState[0:n]
 | 
			
		||||
	s.redo = false
 | 
			
		||||
	if n == 0 {
 | 
			
		||||
		s.step = stateEndTop
 | 
			
		||||
		s.endTop = true
 | 
			
		||||
	} else {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isSpace(c byte) bool {
 | 
			
		||||
	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginValueOrEmpty is the state after reading `[`.
 | 
			
		||||
func stateBeginValueOrEmpty(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	if c == ']' {
 | 
			
		||||
		return stateEndValue(s, c)
 | 
			
		||||
	}
 | 
			
		||||
	return stateBeginValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginValue is the state at the beginning of the input.
 | 
			
		||||
func stateBeginValue(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	switch c {
 | 
			
		||||
	case '{':
 | 
			
		||||
		s.step = stateBeginStringOrEmpty
 | 
			
		||||
		s.pushParseState(parseObjectKey)
 | 
			
		||||
		return scanBeginObject
 | 
			
		||||
	case '[':
 | 
			
		||||
		s.step = stateBeginValueOrEmpty
 | 
			
		||||
		s.pushParseState(parseArrayValue)
 | 
			
		||||
		return scanBeginArray
 | 
			
		||||
	case '"':
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case '-':
 | 
			
		||||
		s.step = stateNeg
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case '0': // beginning of 0.123
 | 
			
		||||
		s.step = state0
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case 't': // beginning of true
 | 
			
		||||
		s.step = stateT
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case 'f': // beginning of false
 | 
			
		||||
		s.step = stateF
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case 'n': // beginning of null
 | 
			
		||||
		s.step = stateN
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	}
 | 
			
		||||
	if '1' <= c && c <= '9' { // beginning of 1234.5
 | 
			
		||||
		s.step = state1
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "looking for beginning of value")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginStringOrEmpty is the state after reading `{`.
 | 
			
		||||
func stateBeginStringOrEmpty(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	if c == '}' {
 | 
			
		||||
		n := len(s.parseState)
 | 
			
		||||
		s.parseState[n-1] = parseObjectValue
 | 
			
		||||
		return stateEndValue(s, c)
 | 
			
		||||
	}
 | 
			
		||||
	return stateBeginString(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginString is the state after reading `{"key": value,`.
 | 
			
		||||
func stateBeginString(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	if c == '"' {
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "looking for beginning of object key string")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateEndValue is the state after completing a value,
 | 
			
		||||
// such as after reading `{}` or `true` or `["x"`.
 | 
			
		||||
func stateEndValue(s *scanner, c byte) int {
 | 
			
		||||
	n := len(s.parseState)
 | 
			
		||||
	if n == 0 {
 | 
			
		||||
		// Completed top-level before the current byte.
 | 
			
		||||
		s.step = stateEndTop
 | 
			
		||||
		s.endTop = true
 | 
			
		||||
		return stateEndTop(s, c)
 | 
			
		||||
	}
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	ps := s.parseState[n-1]
 | 
			
		||||
	switch ps {
 | 
			
		||||
	case parseObjectKey:
 | 
			
		||||
		if c == ':' {
 | 
			
		||||
			s.parseState[n-1] = parseObjectValue
 | 
			
		||||
			s.step = stateBeginValue
 | 
			
		||||
			return scanObjectKey
 | 
			
		||||
		}
 | 
			
		||||
		return s.error(c, "after object key")
 | 
			
		||||
	case parseObjectValue:
 | 
			
		||||
		if c == ',' {
 | 
			
		||||
			s.parseState[n-1] = parseObjectKey
 | 
			
		||||
			s.step = stateBeginString
 | 
			
		||||
			return scanObjectValue
 | 
			
		||||
		}
 | 
			
		||||
		if c == '}' {
 | 
			
		||||
			s.popParseState()
 | 
			
		||||
			return scanEndObject
 | 
			
		||||
		}
 | 
			
		||||
		return s.error(c, "after object key:value pair")
 | 
			
		||||
	case parseArrayValue:
 | 
			
		||||
		if c == ',' {
 | 
			
		||||
			s.step = stateBeginValue
 | 
			
		||||
			return scanArrayValue
 | 
			
		||||
		}
 | 
			
		||||
		if c == ']' {
 | 
			
		||||
			s.popParseState()
 | 
			
		||||
			return scanEndArray
 | 
			
		||||
		}
 | 
			
		||||
		return s.error(c, "after array element")
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateEndTop is the state after finishing the top-level value,
 | 
			
		||||
// such as after reading `{}` or `[1,2,3]`.
 | 
			
		||||
// Only space characters should be seen now.
 | 
			
		||||
func stateEndTop(s *scanner, c byte) int {
 | 
			
		||||
	if c != ' ' && c != '\t' && c != '\r' && c != '\n' {
 | 
			
		||||
		// Complain about non-space byte on next call.
 | 
			
		||||
		s.error(c, "after top-level value")
 | 
			
		||||
	}
 | 
			
		||||
	return scanEnd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInString is the state after reading `"`.
 | 
			
		||||
func stateInString(s *scanner, c byte) int {
 | 
			
		||||
	if c == '"' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c == '\\' {
 | 
			
		||||
		s.step = stateInStringEsc
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c < 0x20 {
 | 
			
		||||
		return s.error(c, "in string literal")
 | 
			
		||||
	}
 | 
			
		||||
	return scanContinue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEsc is the state after reading `"\` during a quoted string.
 | 
			
		||||
func stateInStringEsc(s *scanner, c byte) int {
 | 
			
		||||
	switch c {
 | 
			
		||||
	case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	case 'u':
 | 
			
		||||
		s.step = stateInStringEscU
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in string escape code")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU is the state after reading `"\u` during a quoted string.
 | 
			
		||||
func stateInStringEscU(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInStringEscU1
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
 | 
			
		||||
func stateInStringEscU1(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInStringEscU12
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
 | 
			
		||||
func stateInStringEscU12(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInStringEscU123
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
 | 
			
		||||
func stateInStringEscU123(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateNeg is the state after reading `-` during a number.
 | 
			
		||||
func stateNeg(s *scanner, c byte) int {
 | 
			
		||||
	if c == '0' {
 | 
			
		||||
		s.step = state0
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if '1' <= c && c <= '9' {
 | 
			
		||||
		s.step = state1
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in numeric literal")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// state1 is the state after reading a non-zero integer during a number,
 | 
			
		||||
// such as after reading `1` or `100` but not `0`.
 | 
			
		||||
func state1(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		s.step = state1
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return state0(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// state0 is the state after reading `0` during a number.
 | 
			
		||||
func state0(s *scanner, c byte) int {
 | 
			
		||||
	if c == '.' {
 | 
			
		||||
		s.step = stateDot
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c == 'e' || c == 'E' {
 | 
			
		||||
		s.step = stateE
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateEndValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateDot is the state after reading the integer and decimal point in a number,
 | 
			
		||||
// such as after reading `1.`.
 | 
			
		||||
func stateDot(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		s.step = stateDot0
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "after decimal point in numeric literal")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateDot0 is the state after reading the integer, decimal point, and subsequent
 | 
			
		||||
// digits of a number, such as after reading `3.14`.
 | 
			
		||||
func stateDot0(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c == 'e' || c == 'E' {
 | 
			
		||||
		s.step = stateE
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateEndValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateE is the state after reading the mantissa and e in a number,
 | 
			
		||||
// such as after reading `314e` or `0.314e`.
 | 
			
		||||
func stateE(s *scanner, c byte) int {
 | 
			
		||||
	if c == '+' || c == '-' {
 | 
			
		||||
		s.step = stateESign
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateESign(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateESign is the state after reading the mantissa, e, and sign in a number,
 | 
			
		||||
// such as after reading `314e-` or `0.314e+`.
 | 
			
		||||
func stateESign(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		s.step = stateE0
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in exponent of numeric literal")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateE0 is the state after reading the mantissa, e, optional sign,
 | 
			
		||||
// and at least one digit of the exponent in a number,
 | 
			
		||||
// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
 | 
			
		||||
func stateE0(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateEndValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateT is the state after reading `t`.
 | 
			
		||||
func stateT(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'r' {
 | 
			
		||||
		s.step = stateTr
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal true (expecting 'r')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateTr is the state after reading `tr`.
 | 
			
		||||
func stateTr(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'u' {
 | 
			
		||||
		s.step = stateTru
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal true (expecting 'u')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateTru is the state after reading `tru`.
 | 
			
		||||
func stateTru(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'e' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal true (expecting 'e')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateF is the state after reading `f`.
 | 
			
		||||
func stateF(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'a' {
 | 
			
		||||
		s.step = stateFa
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 'a')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateFa is the state after reading `fa`.
 | 
			
		||||
func stateFa(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'l' {
 | 
			
		||||
		s.step = stateFal
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 'l')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateFal is the state after reading `fal`.
 | 
			
		||||
func stateFal(s *scanner, c byte) int {
 | 
			
		||||
	if c == 's' {
 | 
			
		||||
		s.step = stateFals
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 's')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateFals is the state after reading `fals`.
 | 
			
		||||
func stateFals(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'e' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 'e')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateN is the state after reading `n`.
 | 
			
		||||
func stateN(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'u' {
 | 
			
		||||
		s.step = stateNu
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal null (expecting 'u')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateNu is the state after reading `nu`.
 | 
			
		||||
func stateNu(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'l' {
 | 
			
		||||
		s.step = stateNul
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal null (expecting 'l')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateNul is the state after reading `nul`.
 | 
			
		||||
func stateNul(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'l' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal null (expecting 'l')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateError is the state after reaching a syntax error,
 | 
			
		||||
// such as after reading `[1}` or `5.1.2`.
 | 
			
		||||
func stateError(s *scanner, c byte) int {
 | 
			
		||||
	return scanError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// error records an error and switches to the error state.
 | 
			
		||||
func (s *scanner) error(c byte, context string) int {
 | 
			
		||||
	s.step = stateError
 | 
			
		||||
	s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
 | 
			
		||||
	return scanError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// quoteChar formats c as a quoted character literal
 | 
			
		||||
func quoteChar(c byte) string {
 | 
			
		||||
	// special cases - different from quoted strings
 | 
			
		||||
	if c == '\'' {
 | 
			
		||||
		return `'\''`
 | 
			
		||||
	}
 | 
			
		||||
	if c == '"' {
 | 
			
		||||
		return `'"'`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// use quoted string with different quotation marks
 | 
			
		||||
	s := strconv.Quote(string(c))
 | 
			
		||||
	return "'" + s[1:len(s)-1] + "'"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// undo causes the scanner to return scanCode from the next state transition.
 | 
			
		||||
// This gives callers a simple 1-byte undo mechanism.
 | 
			
		||||
func (s *scanner) undo(scanCode int) {
 | 
			
		||||
	if s.redo {
 | 
			
		||||
		panic("json: invalid use of scanner")
 | 
			
		||||
	}
 | 
			
		||||
	s.redoCode = scanCode
 | 
			
		||||
	s.redoState = s.step
 | 
			
		||||
	s.step = stateRedo
 | 
			
		||||
	s.redo = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateRedo helps implement the scanner's 1-byte undo.
 | 
			
		||||
func stateRedo(s *scanner, c byte) int {
 | 
			
		||||
	s.redo = false
 | 
			
		||||
	s.step = s.redoState
 | 
			
		||||
	return s.redoCode
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										485
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/stream.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										485
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/stream.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,485 @@
 | 
			
		||||
// Copyright 2010 The Go 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 json
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A Decoder reads and decodes JSON objects from an input stream.
 | 
			
		||||
type Decoder struct {
 | 
			
		||||
	r     io.Reader
 | 
			
		||||
	buf   []byte
 | 
			
		||||
	d     decodeState
 | 
			
		||||
	scanp int // start of unread data in buf
 | 
			
		||||
	scan  scanner
 | 
			
		||||
	err   error
 | 
			
		||||
 | 
			
		||||
	tokenState int
 | 
			
		||||
	tokenStack []int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDecoder returns a new decoder that reads from r.
 | 
			
		||||
//
 | 
			
		||||
// The decoder introduces its own buffering and may
 | 
			
		||||
// read data from r beyond the JSON values requested.
 | 
			
		||||
func NewDecoder(r io.Reader) *Decoder {
 | 
			
		||||
	return &Decoder{r: r}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Deprecated: Use `SetNumberType` instead
 | 
			
		||||
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
 | 
			
		||||
// Number instead of as a float64.
 | 
			
		||||
func (dec *Decoder) UseNumber() { dec.d.numberType = UnmarshalJSONNumber }
 | 
			
		||||
 | 
			
		||||
// SetNumberType causes the Decoder to unmarshal a number into an interface{} as a
 | 
			
		||||
// Number, float64 or int64 depending on `t` enum value.
 | 
			
		||||
func (dec *Decoder) SetNumberType(t NumberUnmarshalType) { dec.d.numberType = t }
 | 
			
		||||
 | 
			
		||||
// Decode reads the next JSON-encoded value from its
 | 
			
		||||
// input and stores it in the value pointed to by v.
 | 
			
		||||
//
 | 
			
		||||
// See the documentation for Unmarshal for details about
 | 
			
		||||
// the conversion of JSON into a Go value.
 | 
			
		||||
func (dec *Decoder) Decode(v interface{}) error {
 | 
			
		||||
	if dec.err != nil {
 | 
			
		||||
		return dec.err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := dec.tokenPrepareForDecode(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !dec.tokenValueAllowed() {
 | 
			
		||||
		return &SyntaxError{msg: "not at beginning of value"}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Read whole value into buffer.
 | 
			
		||||
	n, err := dec.readValue()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
 | 
			
		||||
	dec.scanp += n
 | 
			
		||||
 | 
			
		||||
	// Don't save err from unmarshal into dec.err:
 | 
			
		||||
	// the connection is still usable since we read a complete JSON
 | 
			
		||||
	// object from it before the error happened.
 | 
			
		||||
	err = dec.d.unmarshal(v)
 | 
			
		||||
 | 
			
		||||
	// fixup token streaming state
 | 
			
		||||
	dec.tokenValueEnd()
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Buffered returns a reader of the data remaining in the Decoder's
 | 
			
		||||
// buffer. The reader is valid until the next call to Decode.
 | 
			
		||||
func (dec *Decoder) Buffered() io.Reader {
 | 
			
		||||
	return bytes.NewReader(dec.buf[dec.scanp:])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readValue reads a JSON value into dec.buf.
 | 
			
		||||
// It returns the length of the encoding.
 | 
			
		||||
func (dec *Decoder) readValue() (int, error) {
 | 
			
		||||
	dec.scan.reset()
 | 
			
		||||
 | 
			
		||||
	scanp := dec.scanp
 | 
			
		||||
	var err error
 | 
			
		||||
Input:
 | 
			
		||||
	for {
 | 
			
		||||
		// Look in the buffer for a new value.
 | 
			
		||||
		for i, c := range dec.buf[scanp:] {
 | 
			
		||||
			dec.scan.bytes++
 | 
			
		||||
			v := dec.scan.step(&dec.scan, c)
 | 
			
		||||
			if v == scanEnd {
 | 
			
		||||
				scanp += i
 | 
			
		||||
				break Input
 | 
			
		||||
			}
 | 
			
		||||
			// scanEnd is delayed one byte.
 | 
			
		||||
			// We might block trying to get that byte from src,
 | 
			
		||||
			// so instead invent a space byte.
 | 
			
		||||
			if (v == scanEndObject || v == scanEndArray) && dec.scan.step(&dec.scan, ' ') == scanEnd {
 | 
			
		||||
				scanp += i + 1
 | 
			
		||||
				break Input
 | 
			
		||||
			}
 | 
			
		||||
			if v == scanError {
 | 
			
		||||
				dec.err = dec.scan.err
 | 
			
		||||
				return 0, dec.scan.err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		scanp = len(dec.buf)
 | 
			
		||||
 | 
			
		||||
		// Did the last read have an error?
 | 
			
		||||
		// Delayed until now to allow buffer scan.
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err == io.EOF {
 | 
			
		||||
				if dec.scan.step(&dec.scan, ' ') == scanEnd {
 | 
			
		||||
					break Input
 | 
			
		||||
				}
 | 
			
		||||
				if nonSpace(dec.buf) {
 | 
			
		||||
					err = io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			dec.err = err
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		n := scanp - dec.scanp
 | 
			
		||||
		err = dec.refill()
 | 
			
		||||
		scanp = dec.scanp + n
 | 
			
		||||
	}
 | 
			
		||||
	return scanp - dec.scanp, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dec *Decoder) refill() error {
 | 
			
		||||
	// Make room to read more into the buffer.
 | 
			
		||||
	// First slide down data already consumed.
 | 
			
		||||
	if dec.scanp > 0 {
 | 
			
		||||
		n := copy(dec.buf, dec.buf[dec.scanp:])
 | 
			
		||||
		dec.buf = dec.buf[:n]
 | 
			
		||||
		dec.scanp = 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Grow buffer if not large enough.
 | 
			
		||||
	const minRead = 512
 | 
			
		||||
	if cap(dec.buf)-len(dec.buf) < minRead {
 | 
			
		||||
		newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
 | 
			
		||||
		copy(newBuf, dec.buf)
 | 
			
		||||
		dec.buf = newBuf
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Read.  Delay error for next iteration (after scan).
 | 
			
		||||
	n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
 | 
			
		||||
	dec.buf = dec.buf[0 : len(dec.buf)+n]
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func nonSpace(b []byte) bool {
 | 
			
		||||
	for _, c := range b {
 | 
			
		||||
		if !isSpace(c) {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An Encoder writes JSON objects to an output stream.
 | 
			
		||||
type Encoder struct {
 | 
			
		||||
	w   io.Writer
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewEncoder returns a new encoder that writes to w.
 | 
			
		||||
func NewEncoder(w io.Writer) *Encoder {
 | 
			
		||||
	return &Encoder{w: w}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encode writes the JSON encoding of v to the stream,
 | 
			
		||||
// followed by a newline character.
 | 
			
		||||
//
 | 
			
		||||
// See the documentation for Marshal for details about the
 | 
			
		||||
// conversion of Go values to JSON.
 | 
			
		||||
func (enc *Encoder) Encode(v interface{}) error {
 | 
			
		||||
	if enc.err != nil {
 | 
			
		||||
		return enc.err
 | 
			
		||||
	}
 | 
			
		||||
	e := newEncodeState()
 | 
			
		||||
	err := e.marshal(v)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Terminate each value with a newline.
 | 
			
		||||
	// This makes the output look a little nicer
 | 
			
		||||
	// when debugging, and some kind of space
 | 
			
		||||
	// is required if the encoded value was a number,
 | 
			
		||||
	// so that the reader knows there aren't more
 | 
			
		||||
	// digits coming.
 | 
			
		||||
	e.WriteByte('\n')
 | 
			
		||||
 | 
			
		||||
	if _, err = enc.w.Write(e.Bytes()); err != nil {
 | 
			
		||||
		enc.err = err
 | 
			
		||||
	}
 | 
			
		||||
	encodeStatePool.Put(e)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RawMessage is a raw encoded JSON object.
 | 
			
		||||
// It implements Marshaler and Unmarshaler and can
 | 
			
		||||
// be used to delay JSON decoding or precompute a JSON encoding.
 | 
			
		||||
type RawMessage []byte
 | 
			
		||||
 | 
			
		||||
// MarshalJSON returns *m as the JSON encoding of m.
 | 
			
		||||
func (m *RawMessage) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return *m, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSON sets *m to a copy of data.
 | 
			
		||||
func (m *RawMessage) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
 | 
			
		||||
	}
 | 
			
		||||
	*m = append((*m)[0:0], data...)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Marshaler = (*RawMessage)(nil)
 | 
			
		||||
var _ Unmarshaler = (*RawMessage)(nil)
 | 
			
		||||
 | 
			
		||||
// A Token holds a value of one of these types:
 | 
			
		||||
//
 | 
			
		||||
//	Delim, for the four JSON delimiters [ ] { }
 | 
			
		||||
//	bool, for JSON booleans
 | 
			
		||||
//	float64, for JSON numbers
 | 
			
		||||
//	Number, for JSON numbers
 | 
			
		||||
//	string, for JSON string literals
 | 
			
		||||
//	nil, for JSON null
 | 
			
		||||
//
 | 
			
		||||
type Token interface{}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	tokenTopValue = iota
 | 
			
		||||
	tokenArrayStart
 | 
			
		||||
	tokenArrayValue
 | 
			
		||||
	tokenArrayComma
 | 
			
		||||
	tokenObjectStart
 | 
			
		||||
	tokenObjectKey
 | 
			
		||||
	tokenObjectColon
 | 
			
		||||
	tokenObjectValue
 | 
			
		||||
	tokenObjectComma
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// advance tokenstate from a separator state to a value state
 | 
			
		||||
func (dec *Decoder) tokenPrepareForDecode() error {
 | 
			
		||||
	// Note: Not calling peek before switch, to avoid
 | 
			
		||||
	// putting peek into the standard Decode path.
 | 
			
		||||
	// peek is only called when using the Token API.
 | 
			
		||||
	switch dec.tokenState {
 | 
			
		||||
	case tokenArrayComma:
 | 
			
		||||
		c, err := dec.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if c != ',' {
 | 
			
		||||
			return &SyntaxError{"expected comma after array element", 0}
 | 
			
		||||
		}
 | 
			
		||||
		dec.scanp++
 | 
			
		||||
		dec.tokenState = tokenArrayValue
 | 
			
		||||
	case tokenObjectColon:
 | 
			
		||||
		c, err := dec.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if c != ':' {
 | 
			
		||||
			return &SyntaxError{"expected colon after object key", 0}
 | 
			
		||||
		}
 | 
			
		||||
		dec.scanp++
 | 
			
		||||
		dec.tokenState = tokenObjectValue
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dec *Decoder) tokenValueAllowed() bool {
 | 
			
		||||
	switch dec.tokenState {
 | 
			
		||||
	case tokenTopValue, tokenArrayStart, tokenArrayValue, tokenObjectValue:
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dec *Decoder) tokenValueEnd() {
 | 
			
		||||
	switch dec.tokenState {
 | 
			
		||||
	case tokenArrayStart, tokenArrayValue:
 | 
			
		||||
		dec.tokenState = tokenArrayComma
 | 
			
		||||
	case tokenObjectValue:
 | 
			
		||||
		dec.tokenState = tokenObjectComma
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
 | 
			
		||||
type Delim rune
 | 
			
		||||
 | 
			
		||||
func (d Delim) String() string {
 | 
			
		||||
	return string(d)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Token returns the next JSON token in the input stream.
 | 
			
		||||
// At the end of the input stream, Token returns nil, io.EOF.
 | 
			
		||||
//
 | 
			
		||||
// Token guarantees that the delimiters [ ] { } it returns are
 | 
			
		||||
// properly nested and matched: if Token encounters an unexpected
 | 
			
		||||
// delimiter in the input, it will return an error.
 | 
			
		||||
//
 | 
			
		||||
// The input stream consists of basic JSON values—bool, string,
 | 
			
		||||
// number, and null—along with delimiters [ ] { } of type Delim
 | 
			
		||||
// to mark the start and end of arrays and objects.
 | 
			
		||||
// Commas and colons are elided.
 | 
			
		||||
func (dec *Decoder) Token() (Token, error) {
 | 
			
		||||
	for {
 | 
			
		||||
		c, err := dec.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		switch c {
 | 
			
		||||
		case '[':
 | 
			
		||||
			if !dec.tokenValueAllowed() {
 | 
			
		||||
				return dec.tokenError(c)
 | 
			
		||||
			}
 | 
			
		||||
			dec.scanp++
 | 
			
		||||
			dec.tokenStack = append(dec.tokenStack, dec.tokenState)
 | 
			
		||||
			dec.tokenState = tokenArrayStart
 | 
			
		||||
			return Delim('['), nil
 | 
			
		||||
 | 
			
		||||
		case ']':
 | 
			
		||||
			if dec.tokenState != tokenArrayStart && dec.tokenState != tokenArrayComma {
 | 
			
		||||
				return dec.tokenError(c)
 | 
			
		||||
			}
 | 
			
		||||
			dec.scanp++
 | 
			
		||||
			dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
 | 
			
		||||
			dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
 | 
			
		||||
			dec.tokenValueEnd()
 | 
			
		||||
			return Delim(']'), nil
 | 
			
		||||
 | 
			
		||||
		case '{':
 | 
			
		||||
			if !dec.tokenValueAllowed() {
 | 
			
		||||
				return dec.tokenError(c)
 | 
			
		||||
			}
 | 
			
		||||
			dec.scanp++
 | 
			
		||||
			dec.tokenStack = append(dec.tokenStack, dec.tokenState)
 | 
			
		||||
			dec.tokenState = tokenObjectStart
 | 
			
		||||
			return Delim('{'), nil
 | 
			
		||||
 | 
			
		||||
		case '}':
 | 
			
		||||
			if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma {
 | 
			
		||||
				return dec.tokenError(c)
 | 
			
		||||
			}
 | 
			
		||||
			dec.scanp++
 | 
			
		||||
			dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
 | 
			
		||||
			dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
 | 
			
		||||
			dec.tokenValueEnd()
 | 
			
		||||
			return Delim('}'), nil
 | 
			
		||||
 | 
			
		||||
		case ':':
 | 
			
		||||
			if dec.tokenState != tokenObjectColon {
 | 
			
		||||
				return dec.tokenError(c)
 | 
			
		||||
			}
 | 
			
		||||
			dec.scanp++
 | 
			
		||||
			dec.tokenState = tokenObjectValue
 | 
			
		||||
			continue
 | 
			
		||||
 | 
			
		||||
		case ',':
 | 
			
		||||
			if dec.tokenState == tokenArrayComma {
 | 
			
		||||
				dec.scanp++
 | 
			
		||||
				dec.tokenState = tokenArrayValue
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if dec.tokenState == tokenObjectComma {
 | 
			
		||||
				dec.scanp++
 | 
			
		||||
				dec.tokenState = tokenObjectKey
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			return dec.tokenError(c)
 | 
			
		||||
 | 
			
		||||
		case '"':
 | 
			
		||||
			if dec.tokenState == tokenObjectStart || dec.tokenState == tokenObjectKey {
 | 
			
		||||
				var x string
 | 
			
		||||
				old := dec.tokenState
 | 
			
		||||
				dec.tokenState = tokenTopValue
 | 
			
		||||
				err := dec.Decode(&x)
 | 
			
		||||
				dec.tokenState = old
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					clearOffset(err)
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				dec.tokenState = tokenObjectColon
 | 
			
		||||
				return x, nil
 | 
			
		||||
			}
 | 
			
		||||
			fallthrough
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			if !dec.tokenValueAllowed() {
 | 
			
		||||
				return dec.tokenError(c)
 | 
			
		||||
			}
 | 
			
		||||
			var x interface{}
 | 
			
		||||
			if err := dec.Decode(&x); err != nil {
 | 
			
		||||
				clearOffset(err)
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			return x, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clearOffset(err error) {
 | 
			
		||||
	if s, ok := err.(*SyntaxError); ok {
 | 
			
		||||
		s.Offset = 0
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dec *Decoder) tokenError(c byte) (Token, error) {
 | 
			
		||||
	var context string
 | 
			
		||||
	switch dec.tokenState {
 | 
			
		||||
	case tokenTopValue:
 | 
			
		||||
		context = " looking for beginning of value"
 | 
			
		||||
	case tokenArrayStart, tokenArrayValue, tokenObjectValue:
 | 
			
		||||
		context = " looking for beginning of value"
 | 
			
		||||
	case tokenArrayComma:
 | 
			
		||||
		context = " after array element"
 | 
			
		||||
	case tokenObjectKey:
 | 
			
		||||
		context = " looking for beginning of object key string"
 | 
			
		||||
	case tokenObjectColon:
 | 
			
		||||
		context = " after object key"
 | 
			
		||||
	case tokenObjectComma:
 | 
			
		||||
		context = " after object key:value pair"
 | 
			
		||||
	}
 | 
			
		||||
	return nil, &SyntaxError{"invalid character " + quoteChar(c) + " " + context, 0}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// More reports whether there is another element in the
 | 
			
		||||
// current array or object being parsed.
 | 
			
		||||
func (dec *Decoder) More() bool {
 | 
			
		||||
	c, err := dec.peek()
 | 
			
		||||
	return err == nil && c != ']' && c != '}'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dec *Decoder) peek() (byte, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	for {
 | 
			
		||||
		for i := dec.scanp; i < len(dec.buf); i++ {
 | 
			
		||||
			c := dec.buf[i]
 | 
			
		||||
			if isSpace(c) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			dec.scanp = i
 | 
			
		||||
			return c, nil
 | 
			
		||||
		}
 | 
			
		||||
		// buffer has been scanned, now report any error
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		err = dec.refill()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
TODO
 | 
			
		||||
 | 
			
		||||
// EncodeToken writes the given JSON token to the stream.
 | 
			
		||||
// It returns an error if the delimiters [ ] { } are not properly used.
 | 
			
		||||
//
 | 
			
		||||
// EncodeToken does not call Flush, because usually it is part of
 | 
			
		||||
// a larger operation such as Encode, and those will call Flush when finished.
 | 
			
		||||
// Callers that create an Encoder and then invoke EncodeToken directly,
 | 
			
		||||
// without using Encode, need to call Flush when finished to ensure that
 | 
			
		||||
// the JSON is written to the underlying writer.
 | 
			
		||||
func (e *Encoder) EncodeToken(t Token) error  {
 | 
			
		||||
	...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
							
								
								
									
										44
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/tags.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/json/tags.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
// Copyright 2011 The Go 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 json
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// tagOptions is the string following a comma in a struct field's "json"
 | 
			
		||||
// tag, or the empty string. It does not include the leading comma.
 | 
			
		||||
type tagOptions string
 | 
			
		||||
 | 
			
		||||
// parseTag splits a struct field's json tag into its name and
 | 
			
		||||
// comma-separated options.
 | 
			
		||||
func parseTag(tag string) (string, tagOptions) {
 | 
			
		||||
	if idx := strings.Index(tag, ","); idx != -1 {
 | 
			
		||||
		return tag[:idx], tagOptions(tag[idx+1:])
 | 
			
		||||
	}
 | 
			
		||||
	return tag, tagOptions("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Contains reports whether a comma-separated list of options
 | 
			
		||||
// contains a particular substr flag. substr must be surrounded by a
 | 
			
		||||
// string boundary or commas.
 | 
			
		||||
func (o tagOptions) Contains(optionName string) bool {
 | 
			
		||||
	if len(o) == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	s := string(o)
 | 
			
		||||
	for s != "" {
 | 
			
		||||
		var next string
 | 
			
		||||
		i := strings.Index(s, ",")
 | 
			
		||||
		if i >= 0 {
 | 
			
		||||
			s, next = s[:i], s[i+1:]
 | 
			
		||||
		}
 | 
			
		||||
		if s == optionName {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		s = next
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										294
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/jwe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/jwe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,294 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
 | 
			
		||||
type rawJSONWebEncryption struct {
 | 
			
		||||
	Protected    *byteBuffer        `json:"protected,omitempty"`
 | 
			
		||||
	Unprotected  *rawHeader         `json:"unprotected,omitempty"`
 | 
			
		||||
	Header       *rawHeader         `json:"header,omitempty"`
 | 
			
		||||
	Recipients   []rawRecipientInfo `json:"recipients,omitempty"`
 | 
			
		||||
	Aad          *byteBuffer        `json:"aad,omitempty"`
 | 
			
		||||
	EncryptedKey *byteBuffer        `json:"encrypted_key,omitempty"`
 | 
			
		||||
	Iv           *byteBuffer        `json:"iv,omitempty"`
 | 
			
		||||
	Ciphertext   *byteBuffer        `json:"ciphertext,omitempty"`
 | 
			
		||||
	Tag          *byteBuffer        `json:"tag,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// rawRecipientInfo represents a raw JWE Per-Recipient header JSON object. Used for parsing/serializing.
 | 
			
		||||
type rawRecipientInfo struct {
 | 
			
		||||
	Header       *rawHeader `json:"header,omitempty"`
 | 
			
		||||
	EncryptedKey string     `json:"encrypted_key,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// JSONWebEncryption represents an encrypted JWE object after parsing.
 | 
			
		||||
type JSONWebEncryption struct {
 | 
			
		||||
	Header                   Header
 | 
			
		||||
	protected, unprotected   *rawHeader
 | 
			
		||||
	recipients               []recipientInfo
 | 
			
		||||
	aad, iv, ciphertext, tag []byte
 | 
			
		||||
	original                 *rawJSONWebEncryption
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// recipientInfo represents a raw JWE Per-Recipient header JSON object after parsing.
 | 
			
		||||
type recipientInfo struct {
 | 
			
		||||
	header       *rawHeader
 | 
			
		||||
	encryptedKey []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAuthData retrieves the (optional) authenticated data attached to the object.
 | 
			
		||||
func (obj JSONWebEncryption) GetAuthData() []byte {
 | 
			
		||||
	if obj.aad != nil {
 | 
			
		||||
		out := make([]byte, len(obj.aad))
 | 
			
		||||
		copy(out, obj.aad)
 | 
			
		||||
		return out
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the merged header values
 | 
			
		||||
func (obj JSONWebEncryption) mergedHeaders(recipient *recipientInfo) rawHeader {
 | 
			
		||||
	out := rawHeader{}
 | 
			
		||||
	out.merge(obj.protected)
 | 
			
		||||
	out.merge(obj.unprotected)
 | 
			
		||||
 | 
			
		||||
	if recipient != nil {
 | 
			
		||||
		out.merge(recipient.header)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the additional authenticated data from a JWE object.
 | 
			
		||||
func (obj JSONWebEncryption) computeAuthData() []byte {
 | 
			
		||||
	var protected string
 | 
			
		||||
 | 
			
		||||
	if obj.original != nil && obj.original.Protected != nil {
 | 
			
		||||
		protected = obj.original.Protected.base64()
 | 
			
		||||
	} else if obj.protected != nil {
 | 
			
		||||
		protected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON((obj.protected)))
 | 
			
		||||
	} else {
 | 
			
		||||
		protected = ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	output := []byte(protected)
 | 
			
		||||
	if obj.aad != nil {
 | 
			
		||||
		output = append(output, '.')
 | 
			
		||||
		output = append(output, []byte(base64.RawURLEncoding.EncodeToString(obj.aad))...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return output
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEncrypted parses an encrypted message in compact or full serialization format.
 | 
			
		||||
func ParseEncrypted(input string) (*JSONWebEncryption, error) {
 | 
			
		||||
	input = stripWhitespace(input)
 | 
			
		||||
	if strings.HasPrefix(input, "{") {
 | 
			
		||||
		return parseEncryptedFull(input)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return parseEncryptedCompact(input)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
		if nonce := parsed.Unprotected.getNonce(); nonce != "" {
 | 
			
		||||
			return nil, ErrUnprotectedNonce
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if parsed.Header != nil {
 | 
			
		||||
		if nonce := parsed.Header.getNonce(); 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("go-jose/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.
 | 
			
		||||
	var err error
 | 
			
		||||
	mergedHeaders := obj.mergedHeaders(nil)
 | 
			
		||||
	obj.Header, err = mergedHeaders.sanitized()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(parsed.Recipients) == 0 {
 | 
			
		||||
		obj.recipients = []recipientInfo{
 | 
			
		||||
			{
 | 
			
		||||
				header:       parsed.Header,
 | 
			
		||||
				encryptedKey: parsed.EncryptedKey.bytes(),
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		obj.recipients = make([]recipientInfo, len(parsed.Recipients))
 | 
			
		||||
		for r := range parsed.Recipients {
 | 
			
		||||
			encryptedKey, err := base64.RawURLEncoding.DecodeString(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.getNonce() != "" {
 | 
			
		||||
				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.getAlgorithm() == "" || headers.getEncryption() == "" {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseEncryptedCompact parses a message in compact format.
 | 
			
		||||
func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
 | 
			
		||||
	parts := strings.Split(input, ".")
 | 
			
		||||
	if len(parts) != 5 {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	encryptedKey, err := base64.RawURLEncoding.DecodeString(parts[1])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	iv, err := base64.RawURLEncoding.DecodeString(parts[2])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ciphertext, err := base64.RawURLEncoding.DecodeString(parts[3])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tag, err := base64.RawURLEncoding.DecodeString(parts[4])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw := &rawJSONWebEncryption{
 | 
			
		||||
		Protected:    newBuffer(rawProtected),
 | 
			
		||||
		EncryptedKey: newBuffer(encryptedKey),
 | 
			
		||||
		Iv:           newBuffer(iv),
 | 
			
		||||
		Ciphertext:   newBuffer(ciphertext),
 | 
			
		||||
		Tag:          newBuffer(tag),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return raw.sanitized()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CompactSerialize serializes an object using the compact serialization format.
 | 
			
		||||
func (obj JSONWebEncryption) CompactSerialize() (string, error) {
 | 
			
		||||
	if len(obj.recipients) != 1 || obj.unprotected != nil ||
 | 
			
		||||
		obj.protected == nil || obj.recipients[0].header != nil {
 | 
			
		||||
		return "", ErrNotSupported
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	serializedProtected := mustSerializeJSON(obj.protected)
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"%s.%s.%s.%s.%s",
 | 
			
		||||
		base64.RawURLEncoding.EncodeToString(serializedProtected),
 | 
			
		||||
		base64.RawURLEncoding.EncodeToString(obj.recipients[0].encryptedKey),
 | 
			
		||||
		base64.RawURLEncoding.EncodeToString(obj.iv),
 | 
			
		||||
		base64.RawURLEncoding.EncodeToString(obj.ciphertext),
 | 
			
		||||
		base64.RawURLEncoding.EncodeToString(obj.tag)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FullSerialize serializes an object using the full JSON serialization format.
 | 
			
		||||
func (obj JSONWebEncryption) FullSerialize() string {
 | 
			
		||||
	raw := rawJSONWebEncryption{
 | 
			
		||||
		Unprotected:  obj.unprotected,
 | 
			
		||||
		Iv:           newBuffer(obj.iv),
 | 
			
		||||
		Ciphertext:   newBuffer(obj.ciphertext),
 | 
			
		||||
		EncryptedKey: newBuffer(obj.recipients[0].encryptedKey),
 | 
			
		||||
		Tag:          newBuffer(obj.tag),
 | 
			
		||||
		Aad:          newBuffer(obj.aad),
 | 
			
		||||
		Recipients:   []rawRecipientInfo{},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj.recipients) > 1 {
 | 
			
		||||
		for _, recipient := range obj.recipients {
 | 
			
		||||
			info := rawRecipientInfo{
 | 
			
		||||
				Header:       recipient.header,
 | 
			
		||||
				EncryptedKey: base64.RawURLEncoding.EncodeToString(recipient.encryptedKey),
 | 
			
		||||
			}
 | 
			
		||||
			raw.Recipients = append(raw.Recipients, info)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// Use flattened serialization
 | 
			
		||||
		raw.Header = obj.recipients[0].header
 | 
			
		||||
		raw.EncryptedKey = newBuffer(obj.recipients[0].encryptedKey)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if obj.protected != nil {
 | 
			
		||||
		raw.Protected = newBuffer(mustSerializeJSON(obj.protected))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(mustSerializeJSON(raw))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										760
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/jwk.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										760
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/jwk.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,760 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto"
 | 
			
		||||
	"crypto/ecdsa"
 | 
			
		||||
	"crypto/elliptic"
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"crypto/sha1"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/ed25519"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
 | 
			
		||||
type rawJSONWebKey struct {
 | 
			
		||||
	Use string      `json:"use,omitempty"`
 | 
			
		||||
	Kty string      `json:"kty,omitempty"`
 | 
			
		||||
	Kid string      `json:"kid,omitempty"`
 | 
			
		||||
	Crv string      `json:"crv,omitempty"`
 | 
			
		||||
	Alg string      `json:"alg,omitempty"`
 | 
			
		||||
	K   *byteBuffer `json:"k,omitempty"`
 | 
			
		||||
	X   *byteBuffer `json:"x,omitempty"`
 | 
			
		||||
	Y   *byteBuffer `json:"y,omitempty"`
 | 
			
		||||
	N   *byteBuffer `json:"n,omitempty"`
 | 
			
		||||
	E   *byteBuffer `json:"e,omitempty"`
 | 
			
		||||
	// -- Following fields are only used for private keys --
 | 
			
		||||
	// RSA uses D, P and Q, while ECDSA uses only D. Fields Dp, Dq, and Qi are
 | 
			
		||||
	// completely optional. Therefore for RSA/ECDSA, D != nil is a contract that
 | 
			
		||||
	// we have a private key whereas D == nil means we have only a public key.
 | 
			
		||||
	D  *byteBuffer `json:"d,omitempty"`
 | 
			
		||||
	P  *byteBuffer `json:"p,omitempty"`
 | 
			
		||||
	Q  *byteBuffer `json:"q,omitempty"`
 | 
			
		||||
	Dp *byteBuffer `json:"dp,omitempty"`
 | 
			
		||||
	Dq *byteBuffer `json:"dq,omitempty"`
 | 
			
		||||
	Qi *byteBuffer `json:"qi,omitempty"`
 | 
			
		||||
	// Certificates
 | 
			
		||||
	X5c       []string `json:"x5c,omitempty"`
 | 
			
		||||
	X5u       *url.URL `json:"x5u,omitempty"`
 | 
			
		||||
	X5tSHA1   string   `json:"x5t,omitempty"`
 | 
			
		||||
	X5tSHA256 string   `json:"x5t#S256,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// JSONWebKey represents a public or private key in JWK format.
 | 
			
		||||
type JSONWebKey struct {
 | 
			
		||||
	// Cryptographic key, can be a symmetric or asymmetric key.
 | 
			
		||||
	Key interface{}
 | 
			
		||||
	// Key identifier, parsed from `kid` header.
 | 
			
		||||
	KeyID string
 | 
			
		||||
	// Key algorithm, parsed from `alg` header.
 | 
			
		||||
	Algorithm string
 | 
			
		||||
	// Key use, parsed from `use` header.
 | 
			
		||||
	Use string
 | 
			
		||||
 | 
			
		||||
	// X.509 certificate chain, parsed from `x5c` header.
 | 
			
		||||
	Certificates []*x509.Certificate
 | 
			
		||||
	// X.509 certificate URL, parsed from `x5u` header.
 | 
			
		||||
	CertificatesURL *url.URL
 | 
			
		||||
	// X.509 certificate thumbprint (SHA-1), parsed from `x5t` header.
 | 
			
		||||
	CertificateThumbprintSHA1 []byte
 | 
			
		||||
	// X.509 certificate thumbprint (SHA-256), parsed from `x5t#S256` header.
 | 
			
		||||
	CertificateThumbprintSHA256 []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON serializes the given key to its JSON representation.
 | 
			
		||||
func (k JSONWebKey) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	var raw *rawJSONWebKey
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	switch key := k.Key.(type) {
 | 
			
		||||
	case ed25519.PublicKey:
 | 
			
		||||
		raw = fromEdPublicKey(key)
 | 
			
		||||
	case *ecdsa.PublicKey:
 | 
			
		||||
		raw, err = fromEcPublicKey(key)
 | 
			
		||||
	case *rsa.PublicKey:
 | 
			
		||||
		raw = fromRsaPublicKey(key)
 | 
			
		||||
	case ed25519.PrivateKey:
 | 
			
		||||
		raw, err = fromEdPrivateKey(key)
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
		raw, err = fromEcPrivateKey(key)
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
		raw, err = fromRsaPrivateKey(key)
 | 
			
		||||
	case []byte:
 | 
			
		||||
		raw, err = fromSymmetricKey(key)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw.Kid = k.KeyID
 | 
			
		||||
	raw.Alg = k.Algorithm
 | 
			
		||||
	raw.Use = k.Use
 | 
			
		||||
 | 
			
		||||
	for _, cert := range k.Certificates {
 | 
			
		||||
		raw.X5c = append(raw.X5c, base64.StdEncoding.EncodeToString(cert.Raw))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	x5tSHA1Len := len(k.CertificateThumbprintSHA1)
 | 
			
		||||
	x5tSHA256Len := len(k.CertificateThumbprintSHA256)
 | 
			
		||||
	if x5tSHA1Len > 0 {
 | 
			
		||||
		if x5tSHA1Len != sha1.Size {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
 | 
			
		||||
		}
 | 
			
		||||
		raw.X5tSHA1 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA1)
 | 
			
		||||
	}
 | 
			
		||||
	if x5tSHA256Len > 0 {
 | 
			
		||||
		if x5tSHA256Len != sha256.Size {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
 | 
			
		||||
		}
 | 
			
		||||
		raw.X5tSHA256 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA256)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If cert chain is attached (as opposed to being behind a URL), check the
 | 
			
		||||
	// keys thumbprints to make sure they match what is expected. This is to
 | 
			
		||||
	// ensure we don't accidentally produce a JWK with semantically inconsistent
 | 
			
		||||
	// data in the headers.
 | 
			
		||||
	if len(k.Certificates) > 0 {
 | 
			
		||||
		expectedSHA1 := sha1.Sum(k.Certificates[0].Raw)
 | 
			
		||||
		expectedSHA256 := sha256.Sum256(k.Certificates[0].Raw)
 | 
			
		||||
 | 
			
		||||
		if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) {
 | 
			
		||||
			return nil, errors.New("go-jose/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
 | 
			
		||||
		}
 | 
			
		||||
		if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) {
 | 
			
		||||
			return nil, errors.New("go-jose/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw.X5u = k.CertificatesURL
 | 
			
		||||
 | 
			
		||||
	return json.Marshal(raw)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	certs, err := parseCertificateChain(raw.X5c)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("go-jose/go-jose: failed to unmarshal x5c field: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var key interface{}
 | 
			
		||||
	var certPub interface{}
 | 
			
		||||
	var keyPub interface{}
 | 
			
		||||
 | 
			
		||||
	if len(certs) > 0 {
 | 
			
		||||
		// We need to check that leaf public key matches the key embedded in this
 | 
			
		||||
		// JWK, as required by the standard (see RFC 7517, Section 4.7). Otherwise
 | 
			
		||||
		// the JWK parsed could be semantically invalid. Technically, should also
 | 
			
		||||
		// check key usage fields and other extensions on the cert here, but the
 | 
			
		||||
		// standard doesn't exactly explain how they're supposed to map from the
 | 
			
		||||
		// JWK representation to the X.509 extensions.
 | 
			
		||||
		certPub = certs[0].PublicKey
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch raw.Kty {
 | 
			
		||||
	case "EC":
 | 
			
		||||
		if raw.D != nil {
 | 
			
		||||
			key, err = raw.ecPrivateKey()
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				keyPub = key.(*ecdsa.PrivateKey).Public()
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			key, err = raw.ecPublicKey()
 | 
			
		||||
			keyPub = key
 | 
			
		||||
		}
 | 
			
		||||
	case "RSA":
 | 
			
		||||
		if raw.D != nil {
 | 
			
		||||
			key, err = raw.rsaPrivateKey()
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				keyPub = key.(*rsa.PrivateKey).Public()
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			key, err = raw.rsaPublicKey()
 | 
			
		||||
			keyPub = key
 | 
			
		||||
		}
 | 
			
		||||
	case "oct":
 | 
			
		||||
		if certPub != nil {
 | 
			
		||||
			return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
 | 
			
		||||
		}
 | 
			
		||||
		key, err = raw.symmetricKey()
 | 
			
		||||
	case "OKP":
 | 
			
		||||
		if raw.Crv == "Ed25519" && raw.X != nil {
 | 
			
		||||
			if raw.D != nil {
 | 
			
		||||
				key, err = raw.edPrivateKey()
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					keyPub = key.(ed25519.PrivateKey).Public()
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				key, err = raw.edPublicKey()
 | 
			
		||||
				keyPub = key
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			err = fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv)
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		err = fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if certPub != nil && keyPub != nil {
 | 
			
		||||
		if !reflect.DeepEqual(certPub, keyPub) {
 | 
			
		||||
			return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields to not match")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs}
 | 
			
		||||
 | 
			
		||||
	k.CertificatesURL = raw.X5u
 | 
			
		||||
 | 
			
		||||
	// x5t parameters are base64url-encoded SHA thumbprints
 | 
			
		||||
	// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
 | 
			
		||||
	x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// RFC 7517, Section 4.8 is ambiguous as to whether the digest output should be byte or hex,
 | 
			
		||||
	// for this reason, after base64 decoding, if the size is sha1.Size it's likely that the value is a byte encoded
 | 
			
		||||
	// checksum so we skip this. Otherwise if the checksum was hex encoded we expect a 40 byte sized array so we'll
 | 
			
		||||
	// try to hex decode it. When Marshalling this value we'll always use a base64 encoded version of byte format checksum.
 | 
			
		||||
	if len(x5tSHA1bytes) == 2*sha1.Size {
 | 
			
		||||
		hx, err := hex.DecodeString(string(x5tSHA1bytes))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t: %v", err)
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
		x5tSHA1bytes = hx
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k.CertificateThumbprintSHA1 = x5tSHA1bytes
 | 
			
		||||
 | 
			
		||||
	x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(x5tSHA256bytes) == 2*sha256.Size {
 | 
			
		||||
		hx256, err := hex.DecodeString(string(x5tSHA256bytes))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		x5tSHA256bytes = hx256
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k.CertificateThumbprintSHA256 = x5tSHA256bytes
 | 
			
		||||
 | 
			
		||||
	x5tSHA1Len := len(k.CertificateThumbprintSHA1)
 | 
			
		||||
	x5tSHA256Len := len(k.CertificateThumbprintSHA256)
 | 
			
		||||
	if x5tSHA1Len > 0 && x5tSHA1Len != sha1.Size {
 | 
			
		||||
		return errors.New("go-jose/go-jose: invalid JWK, x5t header is of incorrect size")
 | 
			
		||||
	}
 | 
			
		||||
	if x5tSHA256Len > 0 && x5tSHA256Len != sha256.Size {
 | 
			
		||||
		return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If certificate chain *and* thumbprints are set, verify correctness.
 | 
			
		||||
	if len(k.Certificates) > 0 {
 | 
			
		||||
		leaf := k.Certificates[0]
 | 
			
		||||
		sha1sum := sha1.Sum(leaf.Raw)
 | 
			
		||||
		sha256sum := sha256.Sum256(leaf.Raw)
 | 
			
		||||
 | 
			
		||||
		if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(sha1sum[:], k.CertificateThumbprintSHA1) {
 | 
			
		||||
			return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t value")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(sha256sum[:], k.CertificateThumbprintSHA256) {
 | 
			
		||||
			return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// JSONWebKeySet represents a JWK Set object.
 | 
			
		||||
type JSONWebKeySet struct {
 | 
			
		||||
	Keys []JSONWebKey `json:"keys"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key convenience method returns keys by key ID. Specification states
 | 
			
		||||
// that a JWK Set "SHOULD" use distinct key IDs, but allows for some
 | 
			
		||||
// cases where they are not distinct. Hence method returns a slice
 | 
			
		||||
// of JSONWebKeys.
 | 
			
		||||
func (s *JSONWebKeySet) Key(kid string) []JSONWebKey {
 | 
			
		||||
	var keys []JSONWebKey
 | 
			
		||||
	for _, key := range s.Keys {
 | 
			
		||||
		if key.KeyID == kid {
 | 
			
		||||
			keys = append(keys, key)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return keys
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}`
 | 
			
		||||
const ecThumbprintTemplate = `{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`
 | 
			
		||||
const edThumbprintTemplate = `{"crv":"%s","kty":"OKP","x":"%s"}`
 | 
			
		||||
 | 
			
		||||
func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
 | 
			
		||||
	coordLength := curveSize(curve)
 | 
			
		||||
	crv, err := curveName(curve)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength {
 | 
			
		||||
		return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf(ecThumbprintTemplate, crv,
 | 
			
		||||
		newFixedSizeBuffer(x.Bytes(), coordLength).base64(),
 | 
			
		||||
		newFixedSizeBuffer(y.Bytes(), coordLength).base64()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func rsaThumbprintInput(n *big.Int, e int) (string, error) {
 | 
			
		||||
	return fmt.Sprintf(rsaThumbprintTemplate,
 | 
			
		||||
		newBufferFromInt(uint64(e)).base64(),
 | 
			
		||||
		newBuffer(n.Bytes()).base64()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func edThumbprintInput(ed ed25519.PublicKey) (string, error) {
 | 
			
		||||
	crv := "Ed25519"
 | 
			
		||||
	if len(ed) > 32 {
 | 
			
		||||
		return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf(edThumbprintTemplate, crv,
 | 
			
		||||
		newFixedSizeBuffer(ed, 32).base64()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Thumbprint computes the JWK Thumbprint of a key using the
 | 
			
		||||
// indicated hash algorithm.
 | 
			
		||||
func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
 | 
			
		||||
	var input string
 | 
			
		||||
	var err error
 | 
			
		||||
	switch key := k.Key.(type) {
 | 
			
		||||
	case ed25519.PublicKey:
 | 
			
		||||
		input, err = edThumbprintInput(key)
 | 
			
		||||
	case *ecdsa.PublicKey:
 | 
			
		||||
		input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
		input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
 | 
			
		||||
	case *rsa.PublicKey:
 | 
			
		||||
		input, err = rsaThumbprintInput(key.N, key.E)
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
		input, err = rsaThumbprintInput(key.N, key.E)
 | 
			
		||||
	case ed25519.PrivateKey:
 | 
			
		||||
		input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	h := hash.New()
 | 
			
		||||
	h.Write([]byte(input))
 | 
			
		||||
	return h.Sum(nil), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsPublic returns true if the JWK represents a public key (not symmetric, not private).
 | 
			
		||||
func (k *JSONWebKey) IsPublic() bool {
 | 
			
		||||
	switch k.Key.(type) {
 | 
			
		||||
	case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
 | 
			
		||||
		return true
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Public creates JSONWebKey with corresponding public key if JWK represents asymmetric private key.
 | 
			
		||||
func (k *JSONWebKey) Public() JSONWebKey {
 | 
			
		||||
	if k.IsPublic() {
 | 
			
		||||
		return *k
 | 
			
		||||
	}
 | 
			
		||||
	ret := *k
 | 
			
		||||
	switch key := k.Key.(type) {
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
		ret.Key = key.Public()
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
		ret.Key = key.Public()
 | 
			
		||||
	case ed25519.PrivateKey:
 | 
			
		||||
		ret.Key = key.Public()
 | 
			
		||||
	default:
 | 
			
		||||
		return JSONWebKey{} // returning invalid key
 | 
			
		||||
	}
 | 
			
		||||
	return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Valid checks that the key contains the expected parameters.
 | 
			
		||||
func (k *JSONWebKey) Valid() bool {
 | 
			
		||||
	if k.Key == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	switch key := k.Key.(type) {
 | 
			
		||||
	case *ecdsa.PublicKey:
 | 
			
		||||
		if key.Curve == nil || key.X == nil || key.Y == nil {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
		if key.Curve == nil || key.X == nil || key.Y == nil || key.D == nil {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	case *rsa.PublicKey:
 | 
			
		||||
		if key.N == nil || key.E == 0 {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
		if key.N == nil || key.E == 0 || key.D == nil || len(key.Primes) < 2 {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	case ed25519.PublicKey:
 | 
			
		||||
		if len(key) != 32 {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	case ed25519.PrivateKey:
 | 
			
		||||
		if len(key) != 64 {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) {
 | 
			
		||||
	if key.N == nil || key.E == nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, missing n/e values")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &rsa.PublicKey{
 | 
			
		||||
		N: key.N.bigInt(),
 | 
			
		||||
		E: key.E.toInt(),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromEdPublicKey(pub ed25519.PublicKey) *rawJSONWebKey {
 | 
			
		||||
	return &rawJSONWebKey{
 | 
			
		||||
		Kty: "OKP",
 | 
			
		||||
		Crv: "Ed25519",
 | 
			
		||||
		X:   newBuffer(pub),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromRsaPublicKey(pub *rsa.PublicKey) *rawJSONWebKey {
 | 
			
		||||
	return &rawJSONWebKey{
 | 
			
		||||
		Kty: "RSA",
 | 
			
		||||
		N:   newBuffer(pub.N.Bytes()),
 | 
			
		||||
		E:   newBufferFromInt(uint64(pub.E)),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
 | 
			
		||||
	var curve elliptic.Curve
 | 
			
		||||
	switch key.Crv {
 | 
			
		||||
	case "P-256":
 | 
			
		||||
		curve = elliptic.P256()
 | 
			
		||||
	case "P-384":
 | 
			
		||||
		curve = elliptic.P384()
 | 
			
		||||
	case "P-521":
 | 
			
		||||
		curve = elliptic.P521()
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if key.X == nil || key.Y == nil {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid EC key, missing x/y values")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The length of this octet string MUST be the full size of a coordinate for
 | 
			
		||||
	// the curve specified in the "crv" parameter.
 | 
			
		||||
	// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
 | 
			
		||||
	if curveSize(curve) != len(key.X.data) {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for x")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if curveSize(curve) != len(key.Y.data) {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for y")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	x := key.X.bigInt()
 | 
			
		||||
	y := key.Y.bigInt()
 | 
			
		||||
 | 
			
		||||
	if !curve.IsOnCurve(x, y) {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &ecdsa.PublicKey{
 | 
			
		||||
		Curve: curve,
 | 
			
		||||
		X:     x,
 | 
			
		||||
		Y:     y,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
 | 
			
		||||
	if pub == nil || pub.X == nil || pub.Y == nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (nil, or X/Y missing)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name, err := curveName(pub.Curve)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size := curveSize(pub.Curve)
 | 
			
		||||
 | 
			
		||||
	xBytes := pub.X.Bytes()
 | 
			
		||||
	yBytes := pub.Y.Bytes()
 | 
			
		||||
 | 
			
		||||
	if len(xBytes) > size || len(yBytes) > size {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (X/Y too large)")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key := &rawJSONWebKey{
 | 
			
		||||
		Kty: "EC",
 | 
			
		||||
		Crv: name,
 | 
			
		||||
		X:   newFixedSizeBuffer(xBytes, size),
 | 
			
		||||
		Y:   newFixedSizeBuffer(yBytes, size),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return key, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
 | 
			
		||||
	var missing []string
 | 
			
		||||
	switch {
 | 
			
		||||
	case key.D == nil:
 | 
			
		||||
		missing = append(missing, "D")
 | 
			
		||||
	case key.X == nil:
 | 
			
		||||
		missing = append(missing, "X")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(missing) > 0 {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	privateKey := make([]byte, ed25519.PrivateKeySize)
 | 
			
		||||
	copy(privateKey[0:32], key.D.bytes())
 | 
			
		||||
	copy(privateKey[32:], key.X.bytes())
 | 
			
		||||
	rv := ed25519.PrivateKey(privateKey)
 | 
			
		||||
	return rv, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) {
 | 
			
		||||
	if key.X == nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid Ed key, missing x value")
 | 
			
		||||
	}
 | 
			
		||||
	publicKey := make([]byte, ed25519.PublicKeySize)
 | 
			
		||||
	copy(publicKey[0:32], key.X.bytes())
 | 
			
		||||
	rv := ed25519.PublicKey(publicKey)
 | 
			
		||||
	return rv, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
 | 
			
		||||
	var missing []string
 | 
			
		||||
	switch {
 | 
			
		||||
	case key.N == nil:
 | 
			
		||||
		missing = append(missing, "N")
 | 
			
		||||
	case key.E == nil:
 | 
			
		||||
		missing = append(missing, "E")
 | 
			
		||||
	case key.D == nil:
 | 
			
		||||
		missing = append(missing, "D")
 | 
			
		||||
	case key.P == nil:
 | 
			
		||||
		missing = append(missing, "P")
 | 
			
		||||
	case key.Q == nil:
 | 
			
		||||
		missing = append(missing, "Q")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(missing) > 0 {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rv := &rsa.PrivateKey{
 | 
			
		||||
		PublicKey: rsa.PublicKey{
 | 
			
		||||
			N: key.N.bigInt(),
 | 
			
		||||
			E: key.E.toInt(),
 | 
			
		||||
		},
 | 
			
		||||
		D: key.D.bigInt(),
 | 
			
		||||
		Primes: []*big.Int{
 | 
			
		||||
			key.P.bigInt(),
 | 
			
		||||
			key.Q.bigInt(),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if key.Dp != nil {
 | 
			
		||||
		rv.Precomputed.Dp = key.Dp.bigInt()
 | 
			
		||||
	}
 | 
			
		||||
	if key.Dq != nil {
 | 
			
		||||
		rv.Precomputed.Dq = key.Dq.bigInt()
 | 
			
		||||
	}
 | 
			
		||||
	if key.Qi != nil {
 | 
			
		||||
		rv.Precomputed.Qinv = key.Qi.bigInt()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := rv.Validate()
 | 
			
		||||
	return rv, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromEdPrivateKey(ed ed25519.PrivateKey) (*rawJSONWebKey, error) {
 | 
			
		||||
	raw := fromEdPublicKey(ed25519.PublicKey(ed[32:]))
 | 
			
		||||
 | 
			
		||||
	raw.D = newBuffer(ed[0:32])
 | 
			
		||||
	return raw, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromRsaPrivateKey(rsa *rsa.PrivateKey) (*rawJSONWebKey, error) {
 | 
			
		||||
	if len(rsa.Primes) != 2 {
 | 
			
		||||
		return nil, ErrUnsupportedKeyType
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw := fromRsaPublicKey(&rsa.PublicKey)
 | 
			
		||||
 | 
			
		||||
	raw.D = newBuffer(rsa.D.Bytes())
 | 
			
		||||
	raw.P = newBuffer(rsa.Primes[0].Bytes())
 | 
			
		||||
	raw.Q = newBuffer(rsa.Primes[1].Bytes())
 | 
			
		||||
 | 
			
		||||
	if rsa.Precomputed.Dp != nil {
 | 
			
		||||
		raw.Dp = newBuffer(rsa.Precomputed.Dp.Bytes())
 | 
			
		||||
	}
 | 
			
		||||
	if rsa.Precomputed.Dq != nil {
 | 
			
		||||
		raw.Dq = newBuffer(rsa.Precomputed.Dq.Bytes())
 | 
			
		||||
	}
 | 
			
		||||
	if rsa.Precomputed.Qinv != nil {
 | 
			
		||||
		raw.Qi = newBuffer(rsa.Precomputed.Qinv.Bytes())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return raw, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) {
 | 
			
		||||
	var curve elliptic.Curve
 | 
			
		||||
	switch key.Crv {
 | 
			
		||||
	case "P-256":
 | 
			
		||||
		curve = elliptic.P256()
 | 
			
		||||
	case "P-384":
 | 
			
		||||
		curve = elliptic.P384()
 | 
			
		||||
	case "P-521":
 | 
			
		||||
		curve = elliptic.P521()
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if key.X == nil || key.Y == nil || key.D == nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, missing x/y/d values")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The length of this octet string MUST be the full size of a coordinate for
 | 
			
		||||
	// the curve specified in the "crv" parameter.
 | 
			
		||||
	// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
 | 
			
		||||
	if curveSize(curve) != len(key.X.data) {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for x")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if curveSize(curve) != len(key.Y.data) {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for y")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// https://tools.ietf.org/html/rfc7518#section-6.2.2.1
 | 
			
		||||
	if dSize(curve) != len(key.D.data) {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for d")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	x := key.X.bigInt()
 | 
			
		||||
	y := key.Y.bigInt()
 | 
			
		||||
 | 
			
		||||
	if !curve.IsOnCurve(x, y) {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &ecdsa.PrivateKey{
 | 
			
		||||
		PublicKey: ecdsa.PublicKey{
 | 
			
		||||
			Curve: curve,
 | 
			
		||||
			X:     x,
 | 
			
		||||
			Y:     y,
 | 
			
		||||
		},
 | 
			
		||||
		D: key.D.bigInt(),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromEcPrivateKey(ec *ecdsa.PrivateKey) (*rawJSONWebKey, error) {
 | 
			
		||||
	raw, err := fromEcPublicKey(&ec.PublicKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ec.D == nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw.D = newFixedSizeBuffer(ec.D.Bytes(), dSize(ec.PublicKey.Curve))
 | 
			
		||||
 | 
			
		||||
	return raw, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dSize returns the size in octets for the "d" member of an elliptic curve
 | 
			
		||||
// private key.
 | 
			
		||||
// The length of this octet string MUST be ceiling(log-base-2(n)/8)
 | 
			
		||||
// octets (where n is the order of the curve).
 | 
			
		||||
// https://tools.ietf.org/html/rfc7518#section-6.2.2.1
 | 
			
		||||
func dSize(curve elliptic.Curve) int {
 | 
			
		||||
	order := curve.Params().P
 | 
			
		||||
	bitLen := order.BitLen()
 | 
			
		||||
	size := bitLen / 8
 | 
			
		||||
	if bitLen%8 != 0 {
 | 
			
		||||
		size = size + 1
 | 
			
		||||
	}
 | 
			
		||||
	return size
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fromSymmetricKey(key []byte) (*rawJSONWebKey, error) {
 | 
			
		||||
	return &rawJSONWebKey{
 | 
			
		||||
		Kty: "oct",
 | 
			
		||||
		K:   newBuffer(key),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (key rawJSONWebKey) symmetricKey() ([]byte, error) {
 | 
			
		||||
	if key.K == nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: invalid OCT (symmetric) key, missing k value")
 | 
			
		||||
	}
 | 
			
		||||
	return key.K.bytes(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										366
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/jws.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/jws.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,366 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
 | 
			
		||||
type rawJSONWebSignature struct {
 | 
			
		||||
	Payload    *byteBuffer        `json:"payload,omitempty"`
 | 
			
		||||
	Signatures []rawSignatureInfo `json:"signatures,omitempty"`
 | 
			
		||||
	Protected  *byteBuffer        `json:"protected,omitempty"`
 | 
			
		||||
	Header     *rawHeader         `json:"header,omitempty"`
 | 
			
		||||
	Signature  *byteBuffer        `json:"signature,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// rawSignatureInfo represents a single JWS signature over the JWS payload and protected header.
 | 
			
		||||
type rawSignatureInfo struct {
 | 
			
		||||
	Protected *byteBuffer `json:"protected,omitempty"`
 | 
			
		||||
	Header    *rawHeader  `json:"header,omitempty"`
 | 
			
		||||
	Signature *byteBuffer `json:"signature,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// JSONWebSignature represents a signed JWS object after parsing.
 | 
			
		||||
type JSONWebSignature struct {
 | 
			
		||||
	payload []byte
 | 
			
		||||
	// Signatures attached to this object (may be more than one for multi-sig).
 | 
			
		||||
	// Be careful about accessing these directly, prefer to use Verify() or
 | 
			
		||||
	// VerifyMulti() to ensure that the data you're getting is verified.
 | 
			
		||||
	Signatures []Signature
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Signature represents a single signature over the JWS payload and protected header.
 | 
			
		||||
type Signature struct {
 | 
			
		||||
	// Merged header fields. Contains both protected and unprotected header
 | 
			
		||||
	// values. Prefer using Protected and Unprotected fields instead of this.
 | 
			
		||||
	// Values in this header may or may not have been signed and in general
 | 
			
		||||
	// should not be trusted.
 | 
			
		||||
	Header Header
 | 
			
		||||
 | 
			
		||||
	// Protected header. Values in this header were signed and
 | 
			
		||||
	// will be verified as part of the signature verification process.
 | 
			
		||||
	Protected Header
 | 
			
		||||
 | 
			
		||||
	// Unprotected header. Values in this header were not signed
 | 
			
		||||
	// and in general should not be trusted.
 | 
			
		||||
	Unprotected Header
 | 
			
		||||
 | 
			
		||||
	// The actual signature value
 | 
			
		||||
	Signature []byte
 | 
			
		||||
 | 
			
		||||
	protected *rawHeader
 | 
			
		||||
	header    *rawHeader
 | 
			
		||||
	original  *rawSignatureInfo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseSigned parses a signed message in compact or full serialization format.
 | 
			
		||||
func ParseSigned(signature string) (*JSONWebSignature, error) {
 | 
			
		||||
	signature = stripWhitespace(signature)
 | 
			
		||||
	if strings.HasPrefix(signature, "{") {
 | 
			
		||||
		return parseSignedFull(signature)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return parseSignedCompact(signature, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseDetached parses a signed message in compact serialization format with detached payload.
 | 
			
		||||
func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) {
 | 
			
		||||
	if payload == nil {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: nil payload")
 | 
			
		||||
	}
 | 
			
		||||
	return parseSignedCompact(stripWhitespace(signature), payload)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get a header value
 | 
			
		||||
func (sig Signature) mergedHeaders() rawHeader {
 | 
			
		||||
	out := rawHeader{}
 | 
			
		||||
	out.merge(sig.protected)
 | 
			
		||||
	out.merge(sig.header)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compute data to be signed
 | 
			
		||||
func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature) ([]byte, error) {
 | 
			
		||||
	var authData bytes.Buffer
 | 
			
		||||
 | 
			
		||||
	protectedHeader := new(rawHeader)
 | 
			
		||||
 | 
			
		||||
	if signature.original != nil && signature.original.Protected != nil {
 | 
			
		||||
		if err := json.Unmarshal(signature.original.Protected.bytes(), protectedHeader); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		authData.WriteString(signature.original.Protected.base64())
 | 
			
		||||
	} else if signature.protected != nil {
 | 
			
		||||
		protectedHeader = signature.protected
 | 
			
		||||
		authData.WriteString(base64.RawURLEncoding.EncodeToString(mustSerializeJSON(protectedHeader)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	needsBase64 := true
 | 
			
		||||
 | 
			
		||||
	if protectedHeader != nil {
 | 
			
		||||
		var err error
 | 
			
		||||
		if needsBase64, err = protectedHeader.getB64(); err != nil {
 | 
			
		||||
			needsBase64 = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	authData.WriteByte('.')
 | 
			
		||||
 | 
			
		||||
	if needsBase64 {
 | 
			
		||||
		authData.WriteString(base64.RawURLEncoding.EncodeToString(payload))
 | 
			
		||||
	} else {
 | 
			
		||||
		authData.Write(payload)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return authData.Bytes(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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("go-jose/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
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Check that there is not a nonce in the unprotected header
 | 
			
		||||
		if parsed.Header != nil && parsed.Header.getNonce() != "" {
 | 
			
		||||
			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,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		signature.Header, err = signature.mergedHeaders().sanitized()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if signature.header != nil {
 | 
			
		||||
			signature.Unprotected, err = signature.header.sanitized()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if signature.protected != nil {
 | 
			
		||||
			signature.Protected, err = signature.protected.sanitized()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
 | 
			
		||||
		jwk := signature.Header.JSONWebKey
 | 
			
		||||
		if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
 | 
			
		||||
			return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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.getNonce() != "" {
 | 
			
		||||
			return nil, ErrUnprotectedNonce
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		obj.Signatures[i].Header, err = obj.Signatures[i].mergedHeaders().sanitized()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if obj.Signatures[i].header != nil {
 | 
			
		||||
			obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if obj.Signatures[i].protected != nil {
 | 
			
		||||
			obj.Signatures[i].Protected, err = obj.Signatures[i].protected.sanitized()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		obj.Signatures[i].Signature = sig.Signature.bytes()
 | 
			
		||||
 | 
			
		||||
		// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
 | 
			
		||||
		jwk := obj.Signatures[i].Header.JSONWebKey
 | 
			
		||||
		if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
 | 
			
		||||
			return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Copy value of sig
 | 
			
		||||
		original := sig
 | 
			
		||||
 | 
			
		||||
		obj.Signatures[i].header = sig.Header
 | 
			
		||||
		obj.Signatures[i].original = &original
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return obj, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseSignedCompact parses a message in compact format.
 | 
			
		||||
func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) {
 | 
			
		||||
	parts := strings.Split(input, ".")
 | 
			
		||||
	if len(parts) != 3 {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if parts[1] != "" && payload != nil {
 | 
			
		||||
		return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if payload == nil {
 | 
			
		||||
		payload, err = base64.RawURLEncoding.DecodeString(parts[1])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	signature, err := base64.RawURLEncoding.DecodeString(parts[2])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw := &rawJSONWebSignature{
 | 
			
		||||
		Payload:   newBuffer(payload),
 | 
			
		||||
		Protected: newBuffer(rawProtected),
 | 
			
		||||
		Signature: newBuffer(signature),
 | 
			
		||||
	}
 | 
			
		||||
	return raw.sanitized()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
 | 
			
		||||
	if len(obj.Signatures) != 1 || obj.Signatures[0].header != nil || obj.Signatures[0].protected == nil {
 | 
			
		||||
		return "", ErrNotSupported
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected))
 | 
			
		||||
	payload := ""
 | 
			
		||||
	signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature)
 | 
			
		||||
 | 
			
		||||
	if !detached {
 | 
			
		||||
		payload = base64.RawURLEncoding.EncodeToString(obj.payload)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf("%s.%s.%s", serializedProtected, payload, signature), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CompactSerialize serializes an object using the compact serialization format.
 | 
			
		||||
func (obj JSONWebSignature) CompactSerialize() (string, error) {
 | 
			
		||||
	return obj.compactSerialize(false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DetachedCompactSerialize serializes an object using the compact serialization format with detached payload.
 | 
			
		||||
func (obj JSONWebSignature) DetachedCompactSerialize() (string, error) {
 | 
			
		||||
	return obj.compactSerialize(true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FullSerialize serializes an object using the full JSON serialization format.
 | 
			
		||||
func (obj JSONWebSignature) FullSerialize() string {
 | 
			
		||||
	raw := rawJSONWebSignature{
 | 
			
		||||
		Payload: newBuffer(obj.payload),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj.Signatures) == 1 {
 | 
			
		||||
		if obj.Signatures[0].protected != nil {
 | 
			
		||||
			serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
 | 
			
		||||
			raw.Protected = newBuffer(serializedProtected)
 | 
			
		||||
		}
 | 
			
		||||
		raw.Header = obj.Signatures[0].header
 | 
			
		||||
		raw.Signature = newBuffer(obj.Signatures[0].Signature)
 | 
			
		||||
	} else {
 | 
			
		||||
		raw.Signatures = make([]rawSignatureInfo, len(obj.Signatures))
 | 
			
		||||
		for i, signature := range obj.Signatures {
 | 
			
		||||
			raw.Signatures[i] = rawSignatureInfo{
 | 
			
		||||
				Header:    signature.header,
 | 
			
		||||
				Signature: newBuffer(signature.Signature),
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if signature.protected != nil {
 | 
			
		||||
				raw.Signatures[i].Protected = newBuffer(mustSerializeJSON(signature.protected))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(mustSerializeJSON(raw))
 | 
			
		||||
}
 | 
			
		||||
@@ -21,9 +21,9 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/json"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Builder is a utility for making JSON Web Tokens. Calls can be chained, and
 | 
			
		||||
@@ -21,7 +21,7 @@ import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/json"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Claims represents public claim values (as specified in RFC 7519).
 | 
			
		||||
@@ -20,34 +20,34 @@ package jwt
 | 
			
		||||
import "errors"
 | 
			
		||||
 | 
			
		||||
// ErrUnmarshalAudience indicates that aud claim could not be unmarshalled.
 | 
			
		||||
var ErrUnmarshalAudience = errors.New("square/go-jose/jwt: expected string or array value to unmarshal to Audience")
 | 
			
		||||
var ErrUnmarshalAudience = errors.New("go-jose/go-jose/jwt: expected string or array value to unmarshal to Audience")
 | 
			
		||||
 | 
			
		||||
// ErrUnmarshalNumericDate indicates that JWT NumericDate could not be unmarshalled.
 | 
			
		||||
var ErrUnmarshalNumericDate = errors.New("square/go-jose/jwt: expected number value to unmarshal NumericDate")
 | 
			
		||||
var ErrUnmarshalNumericDate = errors.New("go-jose/go-jose/jwt: expected number value to unmarshal NumericDate")
 | 
			
		||||
 | 
			
		||||
// ErrInvalidClaims indicates that given claims have invalid type.
 | 
			
		||||
var ErrInvalidClaims = errors.New("square/go-jose/jwt: expected claims to be value convertible into JSON object")
 | 
			
		||||
var ErrInvalidClaims = errors.New("go-jose/go-jose/jwt: expected claims to be value convertible into JSON object")
 | 
			
		||||
 | 
			
		||||
// ErrInvalidIssuer indicates invalid iss claim.
 | 
			
		||||
var ErrInvalidIssuer = errors.New("square/go-jose/jwt: validation failed, invalid issuer claim (iss)")
 | 
			
		||||
var ErrInvalidIssuer = errors.New("go-jose/go-jose/jwt: validation failed, invalid issuer claim (iss)")
 | 
			
		||||
 | 
			
		||||
// ErrInvalidSubject indicates invalid sub claim.
 | 
			
		||||
var ErrInvalidSubject = errors.New("square/go-jose/jwt: validation failed, invalid subject claim (sub)")
 | 
			
		||||
var ErrInvalidSubject = errors.New("go-jose/go-jose/jwt: validation failed, invalid subject claim (sub)")
 | 
			
		||||
 | 
			
		||||
// ErrInvalidAudience indicated invalid aud claim.
 | 
			
		||||
var ErrInvalidAudience = errors.New("square/go-jose/jwt: validation failed, invalid audience claim (aud)")
 | 
			
		||||
var ErrInvalidAudience = errors.New("go-jose/go-jose/jwt: validation failed, invalid audience claim (aud)")
 | 
			
		||||
 | 
			
		||||
// ErrInvalidID indicates invalid jti claim.
 | 
			
		||||
var ErrInvalidID = errors.New("square/go-jose/jwt: validation failed, invalid ID claim (jti)")
 | 
			
		||||
var ErrInvalidID = errors.New("go-jose/go-jose/jwt: validation failed, invalid ID claim (jti)")
 | 
			
		||||
 | 
			
		||||
// ErrNotValidYet indicates that token is used before time indicated in nbf claim.
 | 
			
		||||
var ErrNotValidYet = errors.New("square/go-jose/jwt: validation failed, token not valid yet (nbf)")
 | 
			
		||||
var ErrNotValidYet = errors.New("go-jose/go-jose/jwt: validation failed, token not valid yet (nbf)")
 | 
			
		||||
 | 
			
		||||
// ErrExpired indicates that token is used after expiry time indicated in exp claim.
 | 
			
		||||
var ErrExpired = errors.New("square/go-jose/jwt: validation failed, token is expired (exp)")
 | 
			
		||||
var ErrExpired = errors.New("go-jose/go-jose/jwt: validation failed, token is expired (exp)")
 | 
			
		||||
 | 
			
		||||
// ErrIssuedInTheFuture indicates that the iat field is in the future.
 | 
			
		||||
var ErrIssuedInTheFuture = errors.New("square/go-jose/jwt: validation field, token issued in the future (iat)")
 | 
			
		||||
var ErrIssuedInTheFuture = errors.New("go-jose/go-jose/jwt: validation field, token issued in the future (iat)")
 | 
			
		||||
 | 
			
		||||
// ErrInvalidContentType indicates that token requires JWT cty header.
 | 
			
		||||
var ErrInvalidContentType = errors.New("square/go-jose/jwt: expected content type to be JWT (cty header)")
 | 
			
		||||
var ErrInvalidContentType = errors.New("go-jose/go-jose/jwt: expected content type to be JWT (cty header)")
 | 
			
		||||
@@ -21,8 +21,8 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	jose "gopkg.in/square/go-jose.v2"
 | 
			
		||||
	"gopkg.in/square/go-jose.v2/json"
 | 
			
		||||
	jose "gopkg.in/go-jose/go-jose.v2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// JSONWebToken represents a JSON Web Token (as specified in RFC7519).
 | 
			
		||||
@@ -60,7 +60,7 @@ func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error {
 | 
			
		||||
// verified. This function won't work for encrypted JWTs.
 | 
			
		||||
func (t *JSONWebToken) UnsafeClaimsWithoutVerification(dest ...interface{}) error {
 | 
			
		||||
	if t.unverifiedPayload == nil {
 | 
			
		||||
		return fmt.Errorf("square/go-jose: Cannot get unverified claims")
 | 
			
		||||
		return fmt.Errorf("go-jose/go-jose: Cannot get unverified claims")
 | 
			
		||||
	}
 | 
			
		||||
	claims := t.unverifiedPayload()
 | 
			
		||||
	for _, d := range dest {
 | 
			
		||||
							
								
								
									
										144
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/opaque.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/opaque.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2018 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
// OpaqueSigner is an interface that supports signing payloads with opaque
 | 
			
		||||
// private key(s). Private key operations performed by implementers may, for
 | 
			
		||||
// example, occur in a hardware module. An OpaqueSigner may rotate signing keys
 | 
			
		||||
// transparently to the user of this interface.
 | 
			
		||||
type OpaqueSigner interface {
 | 
			
		||||
	// Public returns the public key of the current signing key.
 | 
			
		||||
	Public() *JSONWebKey
 | 
			
		||||
	// Algs returns a list of supported signing algorithms.
 | 
			
		||||
	Algs() []SignatureAlgorithm
 | 
			
		||||
	// SignPayload signs a payload with the current signing key using the given
 | 
			
		||||
	// algorithm.
 | 
			
		||||
	SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type opaqueSigner struct {
 | 
			
		||||
	signer OpaqueSigner
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newOpaqueSigner(alg SignatureAlgorithm, signer OpaqueSigner) (recipientSigInfo, error) {
 | 
			
		||||
	var algSupported bool
 | 
			
		||||
	for _, salg := range signer.Algs() {
 | 
			
		||||
		if alg == salg {
 | 
			
		||||
			algSupported = true
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !algSupported {
 | 
			
		||||
		return recipientSigInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientSigInfo{
 | 
			
		||||
		sigAlg:    alg,
 | 
			
		||||
		publicKey: signer.Public,
 | 
			
		||||
		signer: &opaqueSigner{
 | 
			
		||||
			signer: signer,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *opaqueSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
 | 
			
		||||
	out, err := o.signer.SignPayload(payload, alg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Signature{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Signature{
 | 
			
		||||
		Signature: out,
 | 
			
		||||
		protected: &rawHeader{},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OpaqueVerifier is an interface that supports verifying payloads with opaque
 | 
			
		||||
// public key(s). An OpaqueSigner may rotate signing keys transparently to the
 | 
			
		||||
// user of this interface.
 | 
			
		||||
type OpaqueVerifier interface {
 | 
			
		||||
	VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type opaqueVerifier struct {
 | 
			
		||||
	verifier OpaqueVerifier
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
 | 
			
		||||
	return o.verifier.VerifyPayload(payload, signature, alg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key.
 | 
			
		||||
type OpaqueKeyEncrypter interface {
 | 
			
		||||
	// KeyID returns the kid
 | 
			
		||||
	KeyID() string
 | 
			
		||||
	// Algs returns a list of supported key encryption algorithms.
 | 
			
		||||
	Algs() []KeyAlgorithm
 | 
			
		||||
	// encryptKey encrypts the CEK using the given algorithm.
 | 
			
		||||
	encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type opaqueKeyEncrypter struct {
 | 
			
		||||
	encrypter OpaqueKeyEncrypter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newOpaqueKeyEncrypter(alg KeyAlgorithm, encrypter OpaqueKeyEncrypter) (recipientKeyInfo, error) {
 | 
			
		||||
	var algSupported bool
 | 
			
		||||
	for _, salg := range encrypter.Algs() {
 | 
			
		||||
		if alg == salg {
 | 
			
		||||
			algSupported = true
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !algSupported {
 | 
			
		||||
		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientKeyInfo{
 | 
			
		||||
		keyID:  encrypter.KeyID(),
 | 
			
		||||
		keyAlg: alg,
 | 
			
		||||
		keyEncrypter: &opaqueKeyEncrypter{
 | 
			
		||||
			encrypter: encrypter,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
 | 
			
		||||
	return oke.encrypter.encryptKey(cek, alg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
 | 
			
		||||
type OpaqueKeyDecrypter interface {
 | 
			
		||||
	DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type opaqueKeyDecrypter struct {
 | 
			
		||||
	decrypter OpaqueKeyDecrypter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (okd *opaqueKeyDecrypter) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
 | 
			
		||||
	mergedHeaders := rawHeader{}
 | 
			
		||||
	mergedHeaders.merge(&headers)
 | 
			
		||||
	mergedHeaders.merge(recipient.header)
 | 
			
		||||
 | 
			
		||||
	header, err := mergedHeaders.sanitized()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return okd.decrypter.DecryptKey(recipient.encryptedKey, header)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										520
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/shared.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										520
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/shared.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,520 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/elliptic"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// KeyAlgorithm represents a key management algorithm.
 | 
			
		||||
type KeyAlgorithm string
 | 
			
		||||
 | 
			
		||||
// SignatureAlgorithm represents a signature (or MAC) algorithm.
 | 
			
		||||
type SignatureAlgorithm string
 | 
			
		||||
 | 
			
		||||
// ContentEncryption represents a content encryption algorithm.
 | 
			
		||||
type ContentEncryption string
 | 
			
		||||
 | 
			
		||||
// CompressionAlgorithm represents an algorithm used for plaintext compression.
 | 
			
		||||
type CompressionAlgorithm string
 | 
			
		||||
 | 
			
		||||
// ContentType represents type of the contained data.
 | 
			
		||||
type ContentType string
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrCryptoFailure represents an error in cryptographic primitive. This
 | 
			
		||||
	// occurs when, for example, a message had an invalid authentication tag or
 | 
			
		||||
	// could not be decrypted.
 | 
			
		||||
	ErrCryptoFailure = errors.New("go-jose/go-jose: error in cryptographic primitive")
 | 
			
		||||
 | 
			
		||||
	// ErrUnsupportedAlgorithm indicates that a selected algorithm is not
 | 
			
		||||
	// supported. This occurs when trying to instantiate an encrypter for an
 | 
			
		||||
	// algorithm that is not yet implemented.
 | 
			
		||||
	ErrUnsupportedAlgorithm = errors.New("go-jose/go-jose: unknown/unsupported algorithm")
 | 
			
		||||
 | 
			
		||||
	// ErrUnsupportedKeyType indicates that the given key type/format is not
 | 
			
		||||
	// supported. This occurs when trying to instantiate an encrypter and passing
 | 
			
		||||
	// it a key of an unrecognized type or with unsupported parameters, such as
 | 
			
		||||
	// an RSA private key with more than two primes.
 | 
			
		||||
	ErrUnsupportedKeyType = errors.New("go-jose/go-jose: unsupported key type/format")
 | 
			
		||||
 | 
			
		||||
	// ErrInvalidKeySize indicates that the given key is not the correct size
 | 
			
		||||
	// for the selected algorithm. This can occur, for example, when trying to
 | 
			
		||||
	// encrypt with AES-256 but passing only a 128-bit key as input.
 | 
			
		||||
	ErrInvalidKeySize = errors.New("go-jose/go-jose: invalid key size for algorithm")
 | 
			
		||||
 | 
			
		||||
	// ErrNotSupported serialization of object is not supported. This occurs when
 | 
			
		||||
	// trying to compact-serialize an object which can't be represented in
 | 
			
		||||
	// compact form.
 | 
			
		||||
	ErrNotSupported = errors.New("go-jose/go-jose: compact serialization not supported for object")
 | 
			
		||||
 | 
			
		||||
	// ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a
 | 
			
		||||
	// nonce header parameter was included in an unprotected header object.
 | 
			
		||||
	ErrUnprotectedNonce = errors.New("go-jose/go-jose: Nonce parameter included in unprotected header")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Key management algorithms
 | 
			
		||||
const (
 | 
			
		||||
	ED25519            = KeyAlgorithm("ED25519")
 | 
			
		||||
	RSA1_5             = KeyAlgorithm("RSA1_5")             // RSA-PKCS1v1.5
 | 
			
		||||
	RSA_OAEP           = KeyAlgorithm("RSA-OAEP")           // RSA-OAEP-SHA1
 | 
			
		||||
	RSA_OAEP_256       = KeyAlgorithm("RSA-OAEP-256")       // RSA-OAEP-SHA256
 | 
			
		||||
	A128KW             = KeyAlgorithm("A128KW")             // AES key wrap (128)
 | 
			
		||||
	A192KW             = KeyAlgorithm("A192KW")             // AES key wrap (192)
 | 
			
		||||
	A256KW             = KeyAlgorithm("A256KW")             // AES key wrap (256)
 | 
			
		||||
	DIRECT             = KeyAlgorithm("dir")                // Direct encryption
 | 
			
		||||
	ECDH_ES            = KeyAlgorithm("ECDH-ES")            // ECDH-ES
 | 
			
		||||
	ECDH_ES_A128KW     = KeyAlgorithm("ECDH-ES+A128KW")     // ECDH-ES + AES key wrap (128)
 | 
			
		||||
	ECDH_ES_A192KW     = KeyAlgorithm("ECDH-ES+A192KW")     // ECDH-ES + AES key wrap (192)
 | 
			
		||||
	ECDH_ES_A256KW     = KeyAlgorithm("ECDH-ES+A256KW")     // ECDH-ES + AES key wrap (256)
 | 
			
		||||
	A128GCMKW          = KeyAlgorithm("A128GCMKW")          // AES-GCM key wrap (128)
 | 
			
		||||
	A192GCMKW          = KeyAlgorithm("A192GCMKW")          // AES-GCM key wrap (192)
 | 
			
		||||
	A256GCMKW          = KeyAlgorithm("A256GCMKW")          // AES-GCM key wrap (256)
 | 
			
		||||
	PBES2_HS256_A128KW = KeyAlgorithm("PBES2-HS256+A128KW") // PBES2 + HMAC-SHA256 + AES key wrap (128)
 | 
			
		||||
	PBES2_HS384_A192KW = KeyAlgorithm("PBES2-HS384+A192KW") // PBES2 + HMAC-SHA384 + AES key wrap (192)
 | 
			
		||||
	PBES2_HS512_A256KW = KeyAlgorithm("PBES2-HS512+A256KW") // PBES2 + HMAC-SHA512 + AES key wrap (256)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Signature algorithms
 | 
			
		||||
const (
 | 
			
		||||
	EdDSA = SignatureAlgorithm("EdDSA")
 | 
			
		||||
	HS256 = SignatureAlgorithm("HS256") // HMAC using SHA-256
 | 
			
		||||
	HS384 = SignatureAlgorithm("HS384") // HMAC using SHA-384
 | 
			
		||||
	HS512 = SignatureAlgorithm("HS512") // HMAC using SHA-512
 | 
			
		||||
	RS256 = SignatureAlgorithm("RS256") // RSASSA-PKCS-v1.5 using SHA-256
 | 
			
		||||
	RS384 = SignatureAlgorithm("RS384") // RSASSA-PKCS-v1.5 using SHA-384
 | 
			
		||||
	RS512 = SignatureAlgorithm("RS512") // RSASSA-PKCS-v1.5 using SHA-512
 | 
			
		||||
	ES256 = SignatureAlgorithm("ES256") // ECDSA using P-256 and SHA-256
 | 
			
		||||
	ES384 = SignatureAlgorithm("ES384") // ECDSA using P-384 and SHA-384
 | 
			
		||||
	ES512 = SignatureAlgorithm("ES512") // ECDSA using P-521 and SHA-512
 | 
			
		||||
	PS256 = SignatureAlgorithm("PS256") // RSASSA-PSS using SHA256 and MGF1-SHA256
 | 
			
		||||
	PS384 = SignatureAlgorithm("PS384") // RSASSA-PSS using SHA384 and MGF1-SHA384
 | 
			
		||||
	PS512 = SignatureAlgorithm("PS512") // RSASSA-PSS using SHA512 and MGF1-SHA512
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Content encryption algorithms
 | 
			
		||||
const (
 | 
			
		||||
	A128CBC_HS256 = ContentEncryption("A128CBC-HS256") // AES-CBC + HMAC-SHA256 (128)
 | 
			
		||||
	A192CBC_HS384 = ContentEncryption("A192CBC-HS384") // AES-CBC + HMAC-SHA384 (192)
 | 
			
		||||
	A256CBC_HS512 = ContentEncryption("A256CBC-HS512") // AES-CBC + HMAC-SHA512 (256)
 | 
			
		||||
	A128GCM       = ContentEncryption("A128GCM")       // AES-GCM (128)
 | 
			
		||||
	A192GCM       = ContentEncryption("A192GCM")       // AES-GCM (192)
 | 
			
		||||
	A256GCM       = ContentEncryption("A256GCM")       // AES-GCM (256)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Compression algorithms
 | 
			
		||||
const (
 | 
			
		||||
	NONE    = CompressionAlgorithm("")    // No compression
 | 
			
		||||
	DEFLATE = CompressionAlgorithm("DEF") // DEFLATE (RFC 1951)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A key in the protected header of a JWS object. Use of the Header...
 | 
			
		||||
// constants is preferred to enhance type safety.
 | 
			
		||||
type HeaderKey string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	HeaderType        HeaderKey = "typ" // string
 | 
			
		||||
	HeaderContentType           = "cty" // string
 | 
			
		||||
 | 
			
		||||
	// These are set by go-jose and shouldn't need to be set by consumers of the
 | 
			
		||||
	// library.
 | 
			
		||||
	headerAlgorithm   = "alg"  // string
 | 
			
		||||
	headerEncryption  = "enc"  // ContentEncryption
 | 
			
		||||
	headerCompression = "zip"  // CompressionAlgorithm
 | 
			
		||||
	headerCritical    = "crit" // []string
 | 
			
		||||
 | 
			
		||||
	headerAPU = "apu" // *byteBuffer
 | 
			
		||||
	headerAPV = "apv" // *byteBuffer
 | 
			
		||||
	headerEPK = "epk" // *JSONWebKey
 | 
			
		||||
	headerIV  = "iv"  // *byteBuffer
 | 
			
		||||
	headerTag = "tag" // *byteBuffer
 | 
			
		||||
	headerX5c = "x5c" // []*x509.Certificate
 | 
			
		||||
 | 
			
		||||
	headerJWK   = "jwk"   // *JSONWebKey
 | 
			
		||||
	headerKeyID = "kid"   // string
 | 
			
		||||
	headerNonce = "nonce" // string
 | 
			
		||||
	headerB64   = "b64"   // bool
 | 
			
		||||
 | 
			
		||||
	headerP2C = "p2c" // *byteBuffer (int)
 | 
			
		||||
	headerP2S = "p2s" // *byteBuffer ([]byte)
 | 
			
		||||
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// supportedCritical is the set of supported extensions that are understood and processed.
 | 
			
		||||
var supportedCritical = map[string]bool{
 | 
			
		||||
	headerB64: true,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// rawHeader represents the JOSE header for JWE/JWS objects (used for parsing).
 | 
			
		||||
//
 | 
			
		||||
// The decoding of the constituent items is deferred because we want to marshal
 | 
			
		||||
// some members into particular structs rather than generic maps, but at the
 | 
			
		||||
// same time we need to receive any extra fields unhandled by this library to
 | 
			
		||||
// pass through to consuming code in case it wants to examine them.
 | 
			
		||||
type rawHeader map[HeaderKey]*json.RawMessage
 | 
			
		||||
 | 
			
		||||
// Header represents the read-only JOSE header for JWE/JWS objects.
 | 
			
		||||
type Header struct {
 | 
			
		||||
	KeyID      string
 | 
			
		||||
	JSONWebKey *JSONWebKey
 | 
			
		||||
	Algorithm  string
 | 
			
		||||
	Nonce      string
 | 
			
		||||
 | 
			
		||||
	// Unverified certificate chain parsed from x5c header.
 | 
			
		||||
	certificates []*x509.Certificate
 | 
			
		||||
 | 
			
		||||
	// Any headers not recognised above get unmarshalled
 | 
			
		||||
	// from JSON in a generic manner and placed in this map.
 | 
			
		||||
	ExtraHeaders map[HeaderKey]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Certificates verifies & returns the certificate chain present
 | 
			
		||||
// in the x5c header field of a message, if one was present. Returns
 | 
			
		||||
// an error if there was no x5c header present or the chain could
 | 
			
		||||
// not be validated with the given verify options.
 | 
			
		||||
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
 | 
			
		||||
	if len(h.certificates) == 0 {
 | 
			
		||||
		return nil, errors.New("go-jose/go-jose: no x5c header present in message")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	leaf := h.certificates[0]
 | 
			
		||||
	if opts.Intermediates == nil {
 | 
			
		||||
		opts.Intermediates = x509.NewCertPool()
 | 
			
		||||
		for _, intermediate := range h.certificates[1:] {
 | 
			
		||||
			opts.Intermediates.AddCert(intermediate)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return leaf.Verify(opts)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (parsed rawHeader) set(k HeaderKey, v interface{}) error {
 | 
			
		||||
	b, err := json.Marshal(v)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parsed[k] = makeRawMessage(b)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getString gets a string from the raw JSON, defaulting to "".
 | 
			
		||||
func (parsed rawHeader) getString(k HeaderKey) string {
 | 
			
		||||
	v, ok := parsed[k]
 | 
			
		||||
	if !ok || v == nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	var s string
 | 
			
		||||
	err := json.Unmarshal(*v, &s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getByteBuffer gets a byte buffer from the raw JSON. Returns (nil, nil) if
 | 
			
		||||
// not specified.
 | 
			
		||||
func (parsed rawHeader) getByteBuffer(k HeaderKey) (*byteBuffer, error) {
 | 
			
		||||
	v := parsed[k]
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	var bb *byteBuffer
 | 
			
		||||
	err := json.Unmarshal(*v, &bb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return bb, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getAlgorithm extracts parsed "alg" from the raw JSON as a KeyAlgorithm.
 | 
			
		||||
func (parsed rawHeader) getAlgorithm() KeyAlgorithm {
 | 
			
		||||
	return KeyAlgorithm(parsed.getString(headerAlgorithm))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getSignatureAlgorithm extracts parsed "alg" from the raw JSON as a SignatureAlgorithm.
 | 
			
		||||
func (parsed rawHeader) getSignatureAlgorithm() SignatureAlgorithm {
 | 
			
		||||
	return SignatureAlgorithm(parsed.getString(headerAlgorithm))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getEncryption extracts parsed "enc" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getEncryption() ContentEncryption {
 | 
			
		||||
	return ContentEncryption(parsed.getString(headerEncryption))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getCompression extracts parsed "zip" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getCompression() CompressionAlgorithm {
 | 
			
		||||
	return CompressionAlgorithm(parsed.getString(headerCompression))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (parsed rawHeader) getNonce() string {
 | 
			
		||||
	return parsed.getString(headerNonce)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getEPK extracts parsed "epk" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getEPK() (*JSONWebKey, error) {
 | 
			
		||||
	v := parsed[headerEPK]
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	var epk *JSONWebKey
 | 
			
		||||
	err := json.Unmarshal(*v, &epk)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return epk, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getAPU extracts parsed "apu" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getAPU() (*byteBuffer, error) {
 | 
			
		||||
	return parsed.getByteBuffer(headerAPU)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getAPV extracts parsed "apv" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getAPV() (*byteBuffer, error) {
 | 
			
		||||
	return parsed.getByteBuffer(headerAPV)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getIV extracts parsed "iv" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getIV() (*byteBuffer, error) {
 | 
			
		||||
	return parsed.getByteBuffer(headerIV)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getTag extracts parsed "tag" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getTag() (*byteBuffer, error) {
 | 
			
		||||
	return parsed.getByteBuffer(headerTag)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getJWK extracts parsed "jwk" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getJWK() (*JSONWebKey, error) {
 | 
			
		||||
	v := parsed[headerJWK]
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	var jwk *JSONWebKey
 | 
			
		||||
	err := json.Unmarshal(*v, &jwk)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return jwk, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getCritical extracts parsed "crit" from the raw JSON. If omitted, it
 | 
			
		||||
// returns an empty slice.
 | 
			
		||||
func (parsed rawHeader) getCritical() ([]string, error) {
 | 
			
		||||
	v := parsed[headerCritical]
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var q []string
 | 
			
		||||
	err := json.Unmarshal(*v, &q)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return q, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getS2C extracts parsed "p2c" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getP2C() (int, error) {
 | 
			
		||||
	v := parsed[headerP2C]
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return 0, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var p2c int
 | 
			
		||||
	err := json.Unmarshal(*v, &p2c)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return p2c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getS2S extracts parsed "p2s" from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) getP2S() (*byteBuffer, error) {
 | 
			
		||||
	return parsed.getByteBuffer(headerP2S)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getB64 extracts parsed "b64" from the raw JSON, defaulting to true.
 | 
			
		||||
func (parsed rawHeader) getB64() (bool, error) {
 | 
			
		||||
	v := parsed[headerB64]
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var b64 bool
 | 
			
		||||
	err := json.Unmarshal(*v, &b64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	return b64, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sanitized produces a cleaned-up header object from the raw JSON.
 | 
			
		||||
func (parsed rawHeader) sanitized() (h Header, err error) {
 | 
			
		||||
	for k, v := range parsed {
 | 
			
		||||
		if v == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		switch k {
 | 
			
		||||
		case headerJWK:
 | 
			
		||||
			var jwk *JSONWebKey
 | 
			
		||||
			err = json.Unmarshal(*v, &jwk)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				err = fmt.Errorf("failed to unmarshal JWK: %v: %#v", err, string(*v))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			h.JSONWebKey = jwk
 | 
			
		||||
		case headerKeyID:
 | 
			
		||||
			var s string
 | 
			
		||||
			err = json.Unmarshal(*v, &s)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				err = fmt.Errorf("failed to unmarshal key ID: %v: %#v", err, string(*v))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			h.KeyID = s
 | 
			
		||||
		case headerAlgorithm:
 | 
			
		||||
			var s string
 | 
			
		||||
			err = json.Unmarshal(*v, &s)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				err = fmt.Errorf("failed to unmarshal algorithm: %v: %#v", err, string(*v))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			h.Algorithm = s
 | 
			
		||||
		case headerNonce:
 | 
			
		||||
			var s string
 | 
			
		||||
			err = json.Unmarshal(*v, &s)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				err = fmt.Errorf("failed to unmarshal nonce: %v: %#v", err, string(*v))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			h.Nonce = s
 | 
			
		||||
		case headerX5c:
 | 
			
		||||
			c := []string{}
 | 
			
		||||
			err = json.Unmarshal(*v, &c)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			h.certificates, err = parseCertificateChain(c)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			if h.ExtraHeaders == nil {
 | 
			
		||||
				h.ExtraHeaders = map[HeaderKey]interface{}{}
 | 
			
		||||
			}
 | 
			
		||||
			var v2 interface{}
 | 
			
		||||
			err = json.Unmarshal(*v, &v2)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				err = fmt.Errorf("failed to unmarshal value: %v: %#v", err, string(*v))
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			h.ExtraHeaders[k] = v2
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseCertificateChain(chain []string) ([]*x509.Certificate, error) {
 | 
			
		||||
	out := make([]*x509.Certificate, len(chain))
 | 
			
		||||
	for i, cert := range chain {
 | 
			
		||||
		raw, err := base64.StdEncoding.DecodeString(cert)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		out[i], err = x509.ParseCertificate(raw)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dst rawHeader) isSet(k HeaderKey) bool {
 | 
			
		||||
	dvr := dst[k]
 | 
			
		||||
	if dvr == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var dv interface{}
 | 
			
		||||
	err := json.Unmarshal(*dvr, &dv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if dvStr, ok := dv.(string); ok {
 | 
			
		||||
		return dvStr != ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Merge headers from src into dst, giving precedence to headers from l.
 | 
			
		||||
func (dst rawHeader) merge(src *rawHeader) {
 | 
			
		||||
	if src == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for k, v := range *src {
 | 
			
		||||
		if dst.isSet(k) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dst[k] = v
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get JOSE name of curve
 | 
			
		||||
func curveName(crv elliptic.Curve) (string, error) {
 | 
			
		||||
	switch crv {
 | 
			
		||||
	case elliptic.P256():
 | 
			
		||||
		return "P-256", nil
 | 
			
		||||
	case elliptic.P384():
 | 
			
		||||
		return "P-384", nil
 | 
			
		||||
	case elliptic.P521():
 | 
			
		||||
		return "P-521", nil
 | 
			
		||||
	default:
 | 
			
		||||
		return "", fmt.Errorf("go-jose/go-jose: unsupported/unknown elliptic curve")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get size of curve in bytes
 | 
			
		||||
func curveSize(crv elliptic.Curve) int {
 | 
			
		||||
	bits := crv.Params().BitSize
 | 
			
		||||
 | 
			
		||||
	div := bits / 8
 | 
			
		||||
	mod := bits % 8
 | 
			
		||||
 | 
			
		||||
	if mod == 0 {
 | 
			
		||||
		return div
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return div + 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeRawMessage(b []byte) *json.RawMessage {
 | 
			
		||||
	rm := json.RawMessage(b)
 | 
			
		||||
	return &rm
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										441
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/signing.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										441
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/signing.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,441 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto/ecdsa"
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/ed25519"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NonceSource represents a source of random nonces to go into JWS objects
 | 
			
		||||
type NonceSource interface {
 | 
			
		||||
	Nonce() (string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Signer represents a signer which takes a payload and produces a signed JWS object.
 | 
			
		||||
type Signer interface {
 | 
			
		||||
	Sign(payload []byte) (*JSONWebSignature, error)
 | 
			
		||||
	Options() SignerOptions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SigningKey represents an algorithm/key used to sign a message.
 | 
			
		||||
type SigningKey struct {
 | 
			
		||||
	Algorithm SignatureAlgorithm
 | 
			
		||||
	Key       interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SignerOptions represents options that can be set when creating signers.
 | 
			
		||||
type SignerOptions struct {
 | 
			
		||||
	NonceSource NonceSource
 | 
			
		||||
	EmbedJWK    bool
 | 
			
		||||
 | 
			
		||||
	// Optional map of additional keys to be inserted into the protected header
 | 
			
		||||
	// of a JWS object. Some specifications which make use of JWS like to insert
 | 
			
		||||
	// additional values here. All values must be JSON-serializable.
 | 
			
		||||
	ExtraHeaders map[HeaderKey]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
 | 
			
		||||
// if necessary. It returns itself and so can be used in a fluent style.
 | 
			
		||||
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
 | 
			
		||||
	if so.ExtraHeaders == nil {
 | 
			
		||||
		so.ExtraHeaders = map[HeaderKey]interface{}{}
 | 
			
		||||
	}
 | 
			
		||||
	so.ExtraHeaders[k] = v
 | 
			
		||||
	return so
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithContentType adds a content type ("cty") header and returns the updated
 | 
			
		||||
// SignerOptions.
 | 
			
		||||
func (so *SignerOptions) WithContentType(contentType ContentType) *SignerOptions {
 | 
			
		||||
	return so.WithHeader(HeaderContentType, contentType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithType adds a type ("typ") header and returns the updated SignerOptions.
 | 
			
		||||
func (so *SignerOptions) WithType(typ ContentType) *SignerOptions {
 | 
			
		||||
	return so.WithHeader(HeaderType, typ)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithCritical adds the given names to the critical ("crit") header and returns
 | 
			
		||||
// the updated SignerOptions.
 | 
			
		||||
func (so *SignerOptions) WithCritical(names ...string) *SignerOptions {
 | 
			
		||||
	if so.ExtraHeaders[headerCritical] == nil {
 | 
			
		||||
		so.WithHeader(headerCritical, make([]string, 0, len(names)))
 | 
			
		||||
	}
 | 
			
		||||
	crit := so.ExtraHeaders[headerCritical].([]string)
 | 
			
		||||
	so.ExtraHeaders[headerCritical] = append(crit, names...)
 | 
			
		||||
	return so
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithBase64 adds a base64url-encode payload ("b64") header and returns the updated
 | 
			
		||||
// SignerOptions. When the "b64" value is "false", the payload is not base64 encoded.
 | 
			
		||||
func (so *SignerOptions) WithBase64(b64 bool) *SignerOptions {
 | 
			
		||||
	if !b64 {
 | 
			
		||||
		so.WithHeader(headerB64, b64)
 | 
			
		||||
		so.WithCritical(headerB64)
 | 
			
		||||
	}
 | 
			
		||||
	return so
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type payloadSigner interface {
 | 
			
		||||
	signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type payloadVerifier interface {
 | 
			
		||||
	verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type genericSigner struct {
 | 
			
		||||
	recipients   []recipientSigInfo
 | 
			
		||||
	nonceSource  NonceSource
 | 
			
		||||
	embedJWK     bool
 | 
			
		||||
	extraHeaders map[HeaderKey]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type recipientSigInfo struct {
 | 
			
		||||
	sigAlg    SignatureAlgorithm
 | 
			
		||||
	publicKey func() *JSONWebKey
 | 
			
		||||
	signer    payloadSigner
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func staticPublicKey(jwk *JSONWebKey) func() *JSONWebKey {
 | 
			
		||||
	return func() *JSONWebKey {
 | 
			
		||||
		return jwk
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSigner creates an appropriate signer based on the key type
 | 
			
		||||
func NewSigner(sig SigningKey, opts *SignerOptions) (Signer, error) {
 | 
			
		||||
	return NewMultiSigner([]SigningKey{sig}, opts)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMultiSigner creates a signer for multiple recipients
 | 
			
		||||
func NewMultiSigner(sigs []SigningKey, opts *SignerOptions) (Signer, error) {
 | 
			
		||||
	signer := &genericSigner{recipients: []recipientSigInfo{}}
 | 
			
		||||
 | 
			
		||||
	if opts != nil {
 | 
			
		||||
		signer.nonceSource = opts.NonceSource
 | 
			
		||||
		signer.embedJWK = opts.EmbedJWK
 | 
			
		||||
		signer.extraHeaders = opts.ExtraHeaders
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, sig := range sigs {
 | 
			
		||||
		err := signer.addRecipient(sig.Algorithm, sig.Key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return signer, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newVerifier creates a verifier based on the key type
 | 
			
		||||
func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
 | 
			
		||||
	switch verificationKey := verificationKey.(type) {
 | 
			
		||||
	case ed25519.PublicKey:
 | 
			
		||||
		return &edEncrypterVerifier{
 | 
			
		||||
			publicKey: verificationKey,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case *rsa.PublicKey:
 | 
			
		||||
		return &rsaEncrypterVerifier{
 | 
			
		||||
			publicKey: verificationKey,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case *ecdsa.PublicKey:
 | 
			
		||||
		return &ecEncrypterVerifier{
 | 
			
		||||
			publicKey: verificationKey,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case []byte:
 | 
			
		||||
		return &symmetricMac{
 | 
			
		||||
			key: verificationKey,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case JSONWebKey:
 | 
			
		||||
		return newVerifier(verificationKey.Key)
 | 
			
		||||
	case *JSONWebKey:
 | 
			
		||||
		return newVerifier(verificationKey.Key)
 | 
			
		||||
	}
 | 
			
		||||
	if ov, ok := verificationKey.(OpaqueVerifier); ok {
 | 
			
		||||
		return &opaqueVerifier{verifier: ov}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, ErrUnsupportedKeyType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
 | 
			
		||||
	recipient, err := makeJWSRecipient(alg, signingKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.recipients = append(ctx.recipients, recipient)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipientSigInfo, error) {
 | 
			
		||||
	switch signingKey := signingKey.(type) {
 | 
			
		||||
	case ed25519.PrivateKey:
 | 
			
		||||
		return newEd25519Signer(alg, signingKey)
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
		return newRSASigner(alg, signingKey)
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
		return newECDSASigner(alg, signingKey)
 | 
			
		||||
	case []byte:
 | 
			
		||||
		return newSymmetricSigner(alg, signingKey)
 | 
			
		||||
	case JSONWebKey:
 | 
			
		||||
		return newJWKSigner(alg, signingKey)
 | 
			
		||||
	case *JSONWebKey:
 | 
			
		||||
		return newJWKSigner(alg, *signingKey)
 | 
			
		||||
	}
 | 
			
		||||
	if signer, ok := signingKey.(OpaqueSigner); ok {
 | 
			
		||||
		return newOpaqueSigner(alg, signer)
 | 
			
		||||
	}
 | 
			
		||||
	return recipientSigInfo{}, ErrUnsupportedKeyType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
 | 
			
		||||
	recipient, err := makeJWSRecipient(alg, signingKey.Key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return recipientSigInfo{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if recipient.publicKey != nil && recipient.publicKey() != nil {
 | 
			
		||||
		// recipient.publicKey is a JWK synthesized for embedding when recipientSigInfo
 | 
			
		||||
		// was created for the inner key (such as a RSA or ECDSA public key). It contains
 | 
			
		||||
		// the pub key for embedding, but doesn't have extra params like key id.
 | 
			
		||||
		publicKey := signingKey
 | 
			
		||||
		publicKey.Key = recipient.publicKey().Key
 | 
			
		||||
		recipient.publicKey = staticPublicKey(&publicKey)
 | 
			
		||||
 | 
			
		||||
		// This should be impossible, but let's check anyway.
 | 
			
		||||
		if !recipient.publicKey().IsPublic() {
 | 
			
		||||
			return recipientSigInfo{}, errors.New("go-jose/go-jose: public key was unexpectedly not public")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return recipient, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
 | 
			
		||||
	obj := &JSONWebSignature{}
 | 
			
		||||
	obj.payload = payload
 | 
			
		||||
	obj.Signatures = make([]Signature, len(ctx.recipients))
 | 
			
		||||
 | 
			
		||||
	for i, recipient := range ctx.recipients {
 | 
			
		||||
		protected := map[HeaderKey]interface{}{
 | 
			
		||||
			headerAlgorithm: string(recipient.sigAlg),
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if recipient.publicKey != nil && recipient.publicKey() != nil {
 | 
			
		||||
			// We want to embed the JWK or set the kid header, but not both. Having a protected
 | 
			
		||||
			// header that contains an embedded JWK while also simultaneously containing the kid
 | 
			
		||||
			// header is confusing, and at least in ACME the two are considered to be mutually
 | 
			
		||||
			// exclusive. The fact that both can exist at the same time is a somewhat unfortunate
 | 
			
		||||
			// result of the JOSE spec. We've decided that this library will only include one or
 | 
			
		||||
			// the other to avoid this confusion.
 | 
			
		||||
			//
 | 
			
		||||
			// See https://github.com/go-jose/go-jose/issues/157 for more context.
 | 
			
		||||
			if ctx.embedJWK {
 | 
			
		||||
				protected[headerJWK] = recipient.publicKey()
 | 
			
		||||
			} else {
 | 
			
		||||
				keyID := recipient.publicKey().KeyID
 | 
			
		||||
				if keyID != "" {
 | 
			
		||||
					protected[headerKeyID] = keyID
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ctx.nonceSource != nil {
 | 
			
		||||
			nonce, err := ctx.nonceSource.Nonce()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("go-jose/go-jose: Error generating nonce: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			protected[headerNonce] = nonce
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for k, v := range ctx.extraHeaders {
 | 
			
		||||
			protected[k] = v
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		serializedProtected := mustSerializeJSON(protected)
 | 
			
		||||
		needsBase64 := true
 | 
			
		||||
 | 
			
		||||
		if b64, ok := protected[headerB64]; ok {
 | 
			
		||||
			if needsBase64, ok = b64.(bool); !ok {
 | 
			
		||||
				return nil, errors.New("go-jose/go-jose: Invalid b64 header parameter")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var input bytes.Buffer
 | 
			
		||||
 | 
			
		||||
		input.WriteString(base64.RawURLEncoding.EncodeToString(serializedProtected))
 | 
			
		||||
		input.WriteByte('.')
 | 
			
		||||
 | 
			
		||||
		if needsBase64 {
 | 
			
		||||
			input.WriteString(base64.RawURLEncoding.EncodeToString(payload))
 | 
			
		||||
		} else {
 | 
			
		||||
			input.Write(payload)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		signatureInfo, err := recipient.signer.signPayload(input.Bytes(), recipient.sigAlg)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		signatureInfo.protected = &rawHeader{}
 | 
			
		||||
		for k, v := range protected {
 | 
			
		||||
			b, err := json.Marshal(v)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("go-jose/go-jose: Error marshalling item %#v: %v", k, err)
 | 
			
		||||
			}
 | 
			
		||||
			(*signatureInfo.protected)[k] = makeRawMessage(b)
 | 
			
		||||
		}
 | 
			
		||||
		obj.Signatures[i] = signatureInfo
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return obj, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *genericSigner) Options() SignerOptions {
 | 
			
		||||
	return SignerOptions{
 | 
			
		||||
		NonceSource:  ctx.nonceSource,
 | 
			
		||||
		EmbedJWK:     ctx.embedJWK,
 | 
			
		||||
		ExtraHeaders: ctx.extraHeaders,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Verify validates the signature on the object and returns the payload.
 | 
			
		||||
// This function does not support multi-signature, if you desire multi-sig
 | 
			
		||||
// verification use VerifyMulti instead.
 | 
			
		||||
//
 | 
			
		||||
// Be careful when verifying signatures based on embedded JWKs inside the
 | 
			
		||||
// payload header. You cannot assume that the key received in a payload is
 | 
			
		||||
// trusted.
 | 
			
		||||
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
 | 
			
		||||
	err := obj.DetachedVerify(obj.payload, verificationKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.payload, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnsafePayloadWithoutVerification returns the payload without
 | 
			
		||||
// verifying it. The content returned from this function cannot be
 | 
			
		||||
// trusted.
 | 
			
		||||
func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
 | 
			
		||||
	return obj.payload
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DetachedVerify validates a detached signature on the given payload. In
 | 
			
		||||
// most cases, you will probably want to use Verify instead. DetachedVerify
 | 
			
		||||
// is only useful if you have a payload and signature that are separated from
 | 
			
		||||
// each other.
 | 
			
		||||
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
 | 
			
		||||
	verifier, err := newVerifier(verificationKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj.Signatures) > 1 {
 | 
			
		||||
		return errors.New("go-jose/go-jose: too many signatures in payload; expecting only one")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	signature := obj.Signatures[0]
 | 
			
		||||
	headers := signature.mergedHeaders()
 | 
			
		||||
	critical, err := headers.getCritical()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, name := range critical {
 | 
			
		||||
		if !supportedCritical[name] {
 | 
			
		||||
			return ErrCryptoFailure
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	input, err := obj.computeAuthData(payload, &signature)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ErrCryptoFailure
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	alg := headers.getSignatureAlgorithm()
 | 
			
		||||
	err = verifier.verifyPayload(input, signature.Signature, alg)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ErrCryptoFailure
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VerifyMulti validates (one of the multiple) signatures on the object and
 | 
			
		||||
// returns the index of the signature that was verified, along with the signature
 | 
			
		||||
// object and the payload. We return the signature and index to guarantee that
 | 
			
		||||
// callers are getting the verified value.
 | 
			
		||||
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
 | 
			
		||||
	idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, Signature{}, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return idx, sig, obj.payload, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DetachedVerifyMulti validates a detached signature on the given payload with
 | 
			
		||||
// a signature/object that has potentially multiple signers. This returns the index
 | 
			
		||||
// of the signature that was verified, along with the signature object. We return
 | 
			
		||||
// the signature and index to guarantee that callers are getting the verified value.
 | 
			
		||||
//
 | 
			
		||||
// In most cases, you will probably want to use Verify or VerifyMulti instead.
 | 
			
		||||
// DetachedVerifyMulti is only useful if you have a payload and signature that are
 | 
			
		||||
// separated from each other, and the signature can have multiple signers at the
 | 
			
		||||
// same time.
 | 
			
		||||
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
 | 
			
		||||
	verifier, err := newVerifier(verificationKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, Signature{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
outer:
 | 
			
		||||
	for i, signature := range obj.Signatures {
 | 
			
		||||
		headers := signature.mergedHeaders()
 | 
			
		||||
		critical, err := headers.getCritical()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, name := range critical {
 | 
			
		||||
			if !supportedCritical[name] {
 | 
			
		||||
				continue outer
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		input, err := obj.computeAuthData(payload, &signature)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		alg := headers.getSignatureAlgorithm()
 | 
			
		||||
		err = verifier.verifyPayload(input, signature.Signature, alg)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return i, signature, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1, Signature{}, ErrCryptoFailure
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										487
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/symmetric.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										487
									
								
								vendor/gopkg.in/go-jose/go-jose.v2/symmetric.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,487 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright 2014 Square Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package jose
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"crypto/aes"
 | 
			
		||||
	"crypto/cipher"
 | 
			
		||||
	"crypto/hmac"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"crypto/sha512"
 | 
			
		||||
	"crypto/subtle"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"hash"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/pbkdf2"
 | 
			
		||||
	"gopkg.in/go-jose/go-jose.v2/cipher"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Random reader (stubbed out in tests)
 | 
			
		||||
var RandReader = rand.Reader
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// RFC7518 recommends a minimum of 1,000 iterations:
 | 
			
		||||
	// https://tools.ietf.org/html/rfc7518#section-4.8.1.2
 | 
			
		||||
	// NIST recommends a minimum of 10,000:
 | 
			
		||||
	// https://pages.nist.gov/800-63-3/sp800-63b.html
 | 
			
		||||
	// 1Password uses 100,000:
 | 
			
		||||
	// https://support.1password.com/pbkdf2/
 | 
			
		||||
	defaultP2C = 100000
 | 
			
		||||
	// Default salt size: 128 bits
 | 
			
		||||
	defaultP2SSize = 16
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Dummy key cipher for shared symmetric key mode
 | 
			
		||||
type symmetricKeyCipher struct {
 | 
			
		||||
	key []byte // Pre-shared content-encryption key
 | 
			
		||||
	p2c int    // PBES2 Count
 | 
			
		||||
	p2s []byte // PBES2 Salt Input
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Signer/verifier for MAC modes
 | 
			
		||||
type symmetricMac struct {
 | 
			
		||||
	key []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Input/output from an AEAD operation
 | 
			
		||||
type aeadParts struct {
 | 
			
		||||
	iv, ciphertext, tag []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A content cipher based on an AEAD construction
 | 
			
		||||
type aeadContentCipher struct {
 | 
			
		||||
	keyBytes     int
 | 
			
		||||
	authtagBytes int
 | 
			
		||||
	getAead      func(key []byte) (cipher.AEAD, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Random key generator
 | 
			
		||||
type randomKeyGenerator struct {
 | 
			
		||||
	size int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Static key generator
 | 
			
		||||
type staticKeyGenerator struct {
 | 
			
		||||
	key []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a new content cipher based on AES-GCM
 | 
			
		||||
func newAESGCM(keySize int) contentCipher {
 | 
			
		||||
	return &aeadContentCipher{
 | 
			
		||||
		keyBytes:     keySize,
 | 
			
		||||
		authtagBytes: 16,
 | 
			
		||||
		getAead: func(key []byte) (cipher.AEAD, error) {
 | 
			
		||||
			aes, err := aes.NewCipher(key)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return cipher.NewGCM(aes)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a new content cipher based on AES-CBC+HMAC
 | 
			
		||||
func newAESCBC(keySize int) contentCipher {
 | 
			
		||||
	return &aeadContentCipher{
 | 
			
		||||
		keyBytes:     keySize * 2,
 | 
			
		||||
		authtagBytes: keySize,
 | 
			
		||||
		getAead: func(key []byte) (cipher.AEAD, error) {
 | 
			
		||||
			return josecipher.NewCBCHMAC(key, aes.NewCipher)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get an AEAD cipher object for the given content encryption algorithm
 | 
			
		||||
func getContentCipher(alg ContentEncryption) contentCipher {
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case A128GCM:
 | 
			
		||||
		return newAESGCM(16)
 | 
			
		||||
	case A192GCM:
 | 
			
		||||
		return newAESGCM(24)
 | 
			
		||||
	case A256GCM:
 | 
			
		||||
		return newAESGCM(32)
 | 
			
		||||
	case A128CBC_HS256:
 | 
			
		||||
		return newAESCBC(16)
 | 
			
		||||
	case A192CBC_HS384:
 | 
			
		||||
		return newAESCBC(24)
 | 
			
		||||
	case A256CBC_HS512:
 | 
			
		||||
		return newAESCBC(32)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getPbkdf2Params returns the key length and hash function used in
 | 
			
		||||
// pbkdf2.Key.
 | 
			
		||||
func getPbkdf2Params(alg KeyAlgorithm) (int, func() hash.Hash) {
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case PBES2_HS256_A128KW:
 | 
			
		||||
		return 16, sha256.New
 | 
			
		||||
	case PBES2_HS384_A192KW:
 | 
			
		||||
		return 24, sha512.New384
 | 
			
		||||
	case PBES2_HS512_A256KW:
 | 
			
		||||
		return 32, sha512.New
 | 
			
		||||
	default:
 | 
			
		||||
		panic("invalid algorithm")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getRandomSalt generates a new salt of the given size.
 | 
			
		||||
func getRandomSalt(size int) ([]byte, error) {
 | 
			
		||||
	salt := make([]byte, size)
 | 
			
		||||
	_, err := io.ReadFull(RandReader, salt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return salt, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newSymmetricRecipient creates a JWE encrypter based on AES-GCM key wrap.
 | 
			
		||||
func newSymmetricRecipient(keyAlg KeyAlgorithm, key []byte) (recipientKeyInfo, error) {
 | 
			
		||||
	switch keyAlg {
 | 
			
		||||
	case DIRECT, A128GCMKW, A192GCMKW, A256GCMKW, A128KW, A192KW, A256KW:
 | 
			
		||||
	case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
 | 
			
		||||
	default:
 | 
			
		||||
		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientKeyInfo{
 | 
			
		||||
		keyAlg: keyAlg,
 | 
			
		||||
		keyEncrypter: &symmetricKeyCipher{
 | 
			
		||||
			key: key,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newSymmetricSigner creates a recipientSigInfo based on the given key.
 | 
			
		||||
func newSymmetricSigner(sigAlg SignatureAlgorithm, key []byte) (recipientSigInfo, error) {
 | 
			
		||||
	// Verify that key management algorithm is supported by this encrypter
 | 
			
		||||
	switch sigAlg {
 | 
			
		||||
	case HS256, HS384, HS512:
 | 
			
		||||
	default:
 | 
			
		||||
		return recipientSigInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientSigInfo{
 | 
			
		||||
		sigAlg: sigAlg,
 | 
			
		||||
		signer: &symmetricMac{
 | 
			
		||||
			key: key,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Generate a random key for the given content cipher
 | 
			
		||||
func (ctx randomKeyGenerator) genKey() ([]byte, rawHeader, error) {
 | 
			
		||||
	key := make([]byte, ctx.size)
 | 
			
		||||
	_, err := io.ReadFull(RandReader, key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, rawHeader{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return key, rawHeader{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key size for random generator
 | 
			
		||||
func (ctx randomKeyGenerator) keySize() int {
 | 
			
		||||
	return ctx.size
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Generate a static key (for direct mode)
 | 
			
		||||
func (ctx staticKeyGenerator) genKey() ([]byte, rawHeader, error) {
 | 
			
		||||
	cek := make([]byte, len(ctx.key))
 | 
			
		||||
	copy(cek, ctx.key)
 | 
			
		||||
	return cek, rawHeader{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key size for static generator
 | 
			
		||||
func (ctx staticKeyGenerator) keySize() int {
 | 
			
		||||
	return len(ctx.key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get key size for this cipher
 | 
			
		||||
func (ctx aeadContentCipher) keySize() int {
 | 
			
		||||
	return ctx.keyBytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encrypt some data
 | 
			
		||||
func (ctx aeadContentCipher) encrypt(key, aad, pt []byte) (*aeadParts, error) {
 | 
			
		||||
	// Get a new AEAD instance
 | 
			
		||||
	aead, err := ctx.getAead(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Initialize a new nonce
 | 
			
		||||
	iv := make([]byte, aead.NonceSize())
 | 
			
		||||
	_, err = io.ReadFull(RandReader, iv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ciphertextAndTag := aead.Seal(nil, iv, pt, aad)
 | 
			
		||||
	offset := len(ciphertextAndTag) - ctx.authtagBytes
 | 
			
		||||
 | 
			
		||||
	return &aeadParts{
 | 
			
		||||
		iv:         iv,
 | 
			
		||||
		ciphertext: ciphertextAndTag[:offset],
 | 
			
		||||
		tag:        ciphertextAndTag[offset:],
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decrypt some data
 | 
			
		||||
func (ctx aeadContentCipher) decrypt(key, aad []byte, parts *aeadParts) ([]byte, error) {
 | 
			
		||||
	aead, err := ctx.getAead(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(parts.iv) != aead.NonceSize() || len(parts.tag) < ctx.authtagBytes {
 | 
			
		||||
		return nil, ErrCryptoFailure
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return aead.Open(nil, parts.iv, append(parts.ciphertext, parts.tag...), aad)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encrypt the content encryption key.
 | 
			
		||||
func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case DIRECT:
 | 
			
		||||
		return recipientInfo{
 | 
			
		||||
			header: &rawHeader{},
 | 
			
		||||
		}, nil
 | 
			
		||||
	case A128GCMKW, A192GCMKW, A256GCMKW:
 | 
			
		||||
		aead := newAESGCM(len(ctx.key))
 | 
			
		||||
 | 
			
		||||
		parts, err := aead.encrypt(ctx.key, []byte{}, cek)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return recipientInfo{}, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		header := &rawHeader{}
 | 
			
		||||
		header.set(headerIV, newBuffer(parts.iv))
 | 
			
		||||
		header.set(headerTag, newBuffer(parts.tag))
 | 
			
		||||
 | 
			
		||||
		return recipientInfo{
 | 
			
		||||
			header:       header,
 | 
			
		||||
			encryptedKey: parts.ciphertext,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case A128KW, A192KW, A256KW:
 | 
			
		||||
		block, err := aes.NewCipher(ctx.key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return recipientInfo{}, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		jek, err := josecipher.KeyWrap(block, cek)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return recipientInfo{}, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return recipientInfo{
 | 
			
		||||
			encryptedKey: jek,
 | 
			
		||||
			header:       &rawHeader{},
 | 
			
		||||
		}, nil
 | 
			
		||||
	case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
 | 
			
		||||
		if len(ctx.p2s) == 0 {
 | 
			
		||||
			salt, err := getRandomSalt(defaultP2SSize)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return recipientInfo{}, err
 | 
			
		||||
			}
 | 
			
		||||
			ctx.p2s = salt
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ctx.p2c <= 0 {
 | 
			
		||||
			ctx.p2c = defaultP2C
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// salt is UTF8(Alg) || 0x00 || Salt Input
 | 
			
		||||
		salt := bytes.Join([][]byte{[]byte(alg), ctx.p2s}, []byte{0x00})
 | 
			
		||||
 | 
			
		||||
		// derive key
 | 
			
		||||
		keyLen, h := getPbkdf2Params(alg)
 | 
			
		||||
		key := pbkdf2.Key(ctx.key, salt, ctx.p2c, keyLen, h)
 | 
			
		||||
 | 
			
		||||
		// use AES cipher with derived key
 | 
			
		||||
		block, err := aes.NewCipher(key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return recipientInfo{}, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		jek, err := josecipher.KeyWrap(block, cek)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return recipientInfo{}, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		header := &rawHeader{}
 | 
			
		||||
		header.set(headerP2C, ctx.p2c)
 | 
			
		||||
		header.set(headerP2S, newBuffer(ctx.p2s))
 | 
			
		||||
 | 
			
		||||
		return recipientInfo{
 | 
			
		||||
			encryptedKey: jek,
 | 
			
		||||
			header:       header,
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return recipientInfo{}, ErrUnsupportedAlgorithm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decrypt the content encryption key.
 | 
			
		||||
func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
 | 
			
		||||
	switch headers.getAlgorithm() {
 | 
			
		||||
	case DIRECT:
 | 
			
		||||
		cek := make([]byte, len(ctx.key))
 | 
			
		||||
		copy(cek, ctx.key)
 | 
			
		||||
		return cek, nil
 | 
			
		||||
	case A128GCMKW, A192GCMKW, A256GCMKW:
 | 
			
		||||
		aead := newAESGCM(len(ctx.key))
 | 
			
		||||
 | 
			
		||||
		iv, err := headers.getIV()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid IV: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		tag, err := headers.getTag()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid tag: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		parts := &aeadParts{
 | 
			
		||||
			iv:         iv.bytes(),
 | 
			
		||||
			ciphertext: recipient.encryptedKey,
 | 
			
		||||
			tag:        tag.bytes(),
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cek, err := aead.decrypt(ctx.key, []byte{}, parts)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return cek, nil
 | 
			
		||||
	case A128KW, A192KW, A256KW:
 | 
			
		||||
		block, err := aes.NewCipher(ctx.key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return cek, nil
 | 
			
		||||
	case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
 | 
			
		||||
		p2s, err := headers.getP2S()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if p2s == nil || len(p2s.data) == 0 {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: must be present")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p2c, err := headers.getP2C()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if p2c <= 0 {
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: must be a positive integer")
 | 
			
		||||
		}
 | 
			
		||||
		if p2c > 1000000 {
 | 
			
		||||
			// An unauthenticated attacker can set a high P2C value. Set an upper limit to avoid
 | 
			
		||||
			// DoS attacks.
 | 
			
		||||
			return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: too high")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// salt is UTF8(Alg) || 0x00 || Salt Input
 | 
			
		||||
		alg := headers.getAlgorithm()
 | 
			
		||||
		salt := bytes.Join([][]byte{[]byte(alg), p2s.bytes()}, []byte{0x00})
 | 
			
		||||
 | 
			
		||||
		// derive key
 | 
			
		||||
		keyLen, h := getPbkdf2Params(alg)
 | 
			
		||||
		key := pbkdf2.Key(ctx.key, salt, p2c, keyLen, h)
 | 
			
		||||
 | 
			
		||||
		// use AES cipher with derived key
 | 
			
		||||
		block, err := aes.NewCipher(key)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return cek, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sign the given payload
 | 
			
		||||
func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
 | 
			
		||||
	mac, err := ctx.hmac(payload, alg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Signature{}, errors.New("go-jose/go-jose: failed to compute hmac")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Signature{
 | 
			
		||||
		Signature: mac,
 | 
			
		||||
		protected: &rawHeader{},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Verify the given payload
 | 
			
		||||
func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureAlgorithm) error {
 | 
			
		||||
	expected, err := ctx.hmac(payload, alg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("go-jose/go-jose: failed to compute hmac")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(mac) != len(expected) {
 | 
			
		||||
		return errors.New("go-jose/go-jose: invalid hmac")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	match := subtle.ConstantTimeCompare(mac, expected)
 | 
			
		||||
	if match != 1 {
 | 
			
		||||
		return errors.New("go-jose/go-jose: invalid hmac")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compute the HMAC based on the given alg value
 | 
			
		||||
func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
 | 
			
		||||
	var hash func() hash.Hash
 | 
			
		||||
 | 
			
		||||
	switch alg {
 | 
			
		||||
	case HS256:
 | 
			
		||||
		hash = sha256.New
 | 
			
		||||
	case HS384:
 | 
			
		||||
		hash = sha512.New384
 | 
			
		||||
	case HS512:
 | 
			
		||||
		hash = sha512.New
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, ErrUnsupportedAlgorithm
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hmac := hmac.New(hash, ctx.key)
 | 
			
		||||
 | 
			
		||||
	// According to documentation, Write() on hash never fails
 | 
			
		||||
	_, _ = hmac.Write(payload)
 | 
			
		||||
	return hmac.Sum(nil), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -992,6 +992,12 @@ google.golang.org/protobuf/types/known/wrapperspb
 | 
			
		||||
# gopkg.in/evanphx/json-patch.v4 v4.12.0
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/evanphx/json-patch.v4
 | 
			
		||||
# gopkg.in/go-jose/go-jose.v2 v2.6.3
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2/cipher
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2/json
 | 
			
		||||
gopkg.in/go-jose/go-jose.v2/jwt
 | 
			
		||||
# gopkg.in/inf.v0 v0.9.1
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/inf.v0
 | 
			
		||||
@@ -1003,7 +1009,6 @@ gopkg.in/natefinch/lumberjack.v2
 | 
			
		||||
gopkg.in/square/go-jose.v2
 | 
			
		||||
gopkg.in/square/go-jose.v2/cipher
 | 
			
		||||
gopkg.in/square/go-jose.v2/json
 | 
			
		||||
gopkg.in/square/go-jose.v2/jwt
 | 
			
		||||
# gopkg.in/yaml.v3 v3.0.1
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/yaml.v3
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user