// Verifies signature and certificate chain for JWS tokens with multiple signatures,
// e.g. manifests or company descriptions
// Currently uses the 'OU' field of the certificate to check if the certificate
// was signed by a valid role.
Verifies signature and certificate chain for JWS tokens with multiple signatures,
e.g. manifests or company descriptions
Currently uses the 'OU' field of the certificate to check if the certificate
was signed by a valid role.
// Verifies signature and certificate chain for JWS tokens with multiple signatures // e . g . manifests or company descriptions // Currently uses the ' OU ' field of the certificate to check if the certificate // was signed by a valid role .
func verifyJws(data string, roots *x509.CertPool, roles []string, result *VerificationResult) (ok bool, payload []byte) {
	opts := x509.VerifyOptions{
		KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
		Roots:     roots,
	}
	success := true
	jwsData, err := jose.ParseSigned(data)
	if err != nil {
		result.update(false, fmt.Sprintf("PROCESSING ERROR: Data could not be parsed - %v", err))
		return false, nil
	}
	if len(jwsData.Signatures) == 0 {
		result.update(false, "VERIFICATION ERROR: JWS does not contain signatures")
		return false, nil
	}
	index := make([]int, len(jwsData.Signatures))
	payloads := make([][]byte, len(jwsData.Signatures))
	for i, sig := range jwsData.Signatures {
		certs, err := sig.Protected.Certificates(opts)
		if err == nil {
			result.update(true, fmt.Sprintf("VERIFICATION SUCCESS: Certificate chain for %v: %v", certs[0][0].Subject.OrganizationalUnit[0], certs[0][0].Subject.CommonName))
		} else {
			result.update(false, fmt.Sprintf("VERIFICATION ERROR: Certificate chain: %v", err))
			success = false
			continue
		}
		index[i], _, payloads[i], err = jwsData.VerifyMulti(certs[0][0].PublicKey)
		if err == nil {
			result.update(true, fmt.Sprintf("VERIFICATION SUCCESS: Signature from %v: %v", certs[0][0].Subject.OrganizationalUnit[0], certs[0][0].Subject.CommonName))
		} else {
			result.update(false, fmt.Sprintf("VERIFICATION ERROR: Signature from %v: %v - %v", certs[0][0].Subject.OrganizationalUnit[0], certs[0][0].Subject.CommonName, err))
			success = false
		}
		if index[i] != i {
			result.update(false, fmt.Sprintf("VERIFICATION ERROR: Order of signatures incorrect"))
			success = false
		}
		if i > 0 {
			if bytes.Compare(payloads[i], payloads[i-1]) != 0 {
				result.update(false, "VERIFICATION ERROR: Payloads differ for jws with multiple signatures")
				success = false
			}
		}
		if roles != nil {
			if len(roles) != len(jwsData.Signatures) {
				result.update(false, fmt.Sprintf("VERIFICATION ERROR: Expected %v signatures for JWS (got %v)", len(roles), len(jwsData.Signatures)))
				return false, nil
			}
			r := certs[0][0].Subject.OrganizationalUnit[0]
			if r == roles[i] {
				result.update(true, fmt.Sprintf("VERIFICATION SUCCESS: Role matches expected role %v", r))
			} else {
				result.update(false, fmt.Sprintf("VERIFICATION ERROR: Role %v does not match expected role %v", r, roles[i]))
			}
		}
	}
	payload = payloads[0]
	return success, payload
}
func verifyJws ( data string , roots * x509 . CertPool , roles [ ] string , result * VerificationResult ) ( ok bool , payload [ ] byte ) { opts := x509 . VerifyOptions { KeyUsages : [ ] x509 . ExtKeyUsage { x509 . ExtKeyUsageAny } , Roots : roots , } success := true jwsData , err := jose . ParseSigned ( data ) if err != nil { result . update ( false , fmt . Sprintf ( " " , err ) ) return false , nil } if len ( jwsData . Signatures ) == 0 { result . update ( false , " " ) return false , nil } index := make ( [ ] int , len ( jwsData . Signatures ) ) payloads := make ( [ ] [ ] byte , len ( jwsData . Signatures ) ) for i , sig := range jwsData . Signatures { certs , err := sig . Protected . Certificates ( opts ) if err == nil { result . update ( true , fmt . Sprintf ( " " , certs [ 0 ] [ 0 ] . Subject . OrganizationalUnit [ 0 ] , certs [ 0 ] [ 0 ] . Subject . CommonName ) ) } else { result . update ( false , fmt . Sprintf ( " " , err ) ) success = false continue } index [ i ] , _ , payloads [ i ] , err = jwsData . VerifyMulti ( certs [ 0 ] [ 0 ] . PublicKey ) if err == nil { result . update ( true , fmt . Sprintf ( " " , certs [ 0 ] [ 0 ] . Subject . OrganizationalUnit [ 0 ] , certs [ 0 ] [ 0 ] . Subject . CommonName ) ) } else { result . update ( false , fmt . Sprintf ( " " , certs [ 0 ] [ 0 ] . Subject . OrganizationalUnit [ 0 ] , certs [ 0 ] [ 0 ] . Subject . CommonName , err ) ) success = false } if index [ i ] != i { result . update ( false , fmt . Sprintf ( " " ) ) success = false } if i > 0 { if bytes . Compare ( payloads [ i ] , payloads [ i - 1 ] ) != 0 { result . update ( false , " " ) success = false } } if roles != nil { if len ( roles ) != len ( jwsData . Signatures ) { result . update ( false , fmt . Sprintf ( " " , len ( roles ) , len ( jwsData . Signatures ) ) ) return false , nil } r := certs [ 0 ] [ 0 ] . Subject . OrganizationalUnit [ 0 ] if r == roles [ i ] { result . update ( true , fmt . Sprintf ( " " , r ) ) } else { result . update ( false , fmt . Sprintf ( " " , r , roles [ i ] ) ) } } } payload = payloads [ 0 ] return success , payload }
Verifies signature and certificate chain for JWS tokens with multiple signatures,
e.g.
Verifies signature and certificate chain for JWS tokens with multiple signatures e . g .
//Extract certificates and validate certificate chains in the process // Optionally validate that the JWS token was signed with a certificate with the correct // role which is set in the 'OU' field of the certificate