mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 11:42:25 -05:00 
			
		
		
		
	[feature] Try HTTP signature validation with and without query params for incoming requests (#2591)
* [feature] Verify signatures both with + without query params * Bump to tagged version
This commit is contained in:
		
					parent
					
						
							
								c675d47a8c
							
						
					
				
			
			
				commit
				
					
						b614d33c40
					
				
			
		
					 18 changed files with 1799 additions and 22 deletions
				
			
		
							
								
								
									
										120
									
								
								vendor/github.com/superseriousbusiness/httpsig/digest.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								vendor/github.com/superseriousbusiness/httpsig/digest.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | |||
| package httpsig | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto" | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| 	"hash" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| type DigestAlgorithm string | ||||
| 
 | ||||
| const ( | ||||
| 	DigestSha256 DigestAlgorithm = "SHA-256" | ||||
| 	DigestSha512                 = "SHA-512" | ||||
| ) | ||||
| 
 | ||||
| var digestToDef = map[DigestAlgorithm]crypto.Hash{ | ||||
| 	DigestSha256: crypto.SHA256, | ||||
| 	DigestSha512: crypto.SHA512, | ||||
| } | ||||
| 
 | ||||
| // IsSupportedDigestAlgorithm returns true if hte string is supported by this | ||||
| // library, is not a hash known to be weak, and is supported by the hardware. | ||||
| func IsSupportedDigestAlgorithm(algo string) bool { | ||||
| 	uc := DigestAlgorithm(strings.ToUpper(algo)) | ||||
| 	c, ok := digestToDef[uc] | ||||
| 	return ok && c.Available() | ||||
| } | ||||
| 
 | ||||
| func getHash(alg DigestAlgorithm) (h hash.Hash, toUse DigestAlgorithm, err error) { | ||||
| 	upper := DigestAlgorithm(strings.ToUpper(string(alg))) | ||||
| 	c, ok := digestToDef[upper] | ||||
| 	if !ok { | ||||
| 		err = fmt.Errorf("unknown or unsupported Digest algorithm: %s", alg) | ||||
| 	} else if !c.Available() { | ||||
| 		err = fmt.Errorf("unavailable Digest algorithm: %s", alg) | ||||
| 	} else { | ||||
| 		h = c.New() | ||||
| 		toUse = upper | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	digestHeader = "Digest" | ||||
| 	digestDelim  = "=" | ||||
| ) | ||||
| 
 | ||||
| func addDigest(r *http.Request, algo DigestAlgorithm, b []byte) (err error) { | ||||
| 	_, ok := r.Header[digestHeader] | ||||
| 	if ok { | ||||
| 		err = fmt.Errorf("cannot add Digest: Digest is already set") | ||||
| 		return | ||||
| 	} | ||||
| 	var h hash.Hash | ||||
| 	var a DigestAlgorithm | ||||
| 	h, a, err = getHash(algo) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	h.Write(b) | ||||
| 	sum := h.Sum(nil) | ||||
| 	r.Header.Add(digestHeader, | ||||
| 		fmt.Sprintf("%s%s%s", | ||||
| 			a, | ||||
| 			digestDelim, | ||||
| 			base64.StdEncoding.EncodeToString(sum[:]))) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func addDigestResponse(r http.ResponseWriter, algo DigestAlgorithm, b []byte) (err error) { | ||||
| 	_, ok := r.Header()[digestHeader] | ||||
| 	if ok { | ||||
| 		err = fmt.Errorf("cannot add Digest: Digest is already set") | ||||
| 		return | ||||
| 	} | ||||
| 	var h hash.Hash | ||||
| 	var a DigestAlgorithm | ||||
| 	h, a, err = getHash(algo) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	h.Write(b) | ||||
| 	sum := h.Sum(nil) | ||||
| 	r.Header().Add(digestHeader, | ||||
| 		fmt.Sprintf("%s%s%s", | ||||
| 			a, | ||||
| 			digestDelim, | ||||
| 			base64.StdEncoding.EncodeToString(sum[:]))) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func verifyDigest(r *http.Request, body *bytes.Buffer) (err error) { | ||||
| 	d := r.Header.Get(digestHeader) | ||||
| 	if len(d) == 0 { | ||||
| 		err = fmt.Errorf("cannot verify Digest: request has no Digest header") | ||||
| 		return | ||||
| 	} | ||||
| 	elem := strings.SplitN(d, digestDelim, 2) | ||||
| 	if len(elem) != 2 { | ||||
| 		err = fmt.Errorf("cannot verify Digest: malformed Digest: %s", d) | ||||
| 		return | ||||
| 	} | ||||
| 	var h hash.Hash | ||||
| 	h, _, err = getHash(DigestAlgorithm(elem[0])) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	h.Write(body.Bytes()) | ||||
| 	sum := h.Sum(nil) | ||||
| 	encSum := base64.StdEncoding.EncodeToString(sum[:]) | ||||
| 	if encSum != elem[1] { | ||||
| 		err = fmt.Errorf("cannot verify Digest: header Digest does not match the digest of the request body") | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue