Skip to content

Commit 22f19bd

Browse files
committed
Polishes docs for RSA algorithms
1 parent c15eb40 commit 22f19bd

4 files changed

Lines changed: 132 additions & 24 deletions

File tree

examples_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,38 @@
11
package httpsignatures_test
22

33
import (
4+
"crypto/rsa"
5+
"crypto/x509"
6+
"encoding/pem"
47
"net/http"
58

69
"github.com/99designs/httpsignatures-go"
710
)
811

12+
const (
13+
ExamplePrivateKey = `-----BEGIN RSA PRIVATE KEY-----
14+
MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF
15+
NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F
16+
UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB
17+
AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA
18+
QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK
19+
kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg
20+
f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u
21+
412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc
22+
mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7
23+
kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA
24+
gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW
25+
G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI
26+
7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==
27+
-----END RSA PRIVATE KEY-----`
28+
ExamplePublicyKey = `-----BEGIN PUBLIC KEY-----
29+
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
30+
6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6
31+
Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw
32+
oYi+1hqp1fIekaxsyQIDAQAB
33+
-----END PUBLIC KEY-----`
34+
)
35+
936
func Example_signing() {
1037
r, _ := http.NewRequest("GET", "http://example.com/some-api", nil)
1138

@@ -17,6 +44,20 @@ func Example_signing() {
1744
http.DefaultClient.Do(r)
1845
}
1946

47+
func Example_signingRSA() {
48+
block, _ := pem.Decode([]byte(ExamplePrivateKey))
49+
privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
50+
51+
r, _ := http.NewRequest("GET", "http://example.com/some-api", nil)
52+
53+
// Sign using the 'Signature' header
54+
httpsignatures.DefaultRsaSha256Signer.SignRequestRSA("KeyId", privateKey, r)
55+
// OR Sign using the 'Authorization' header
56+
httpsignatures.DefaultRsaSha256Signer.AuthRequestRSA("KeyId", privateKey, r)
57+
58+
http.DefaultClient.Do(r)
59+
}
60+
2061
func Example_customSigning() {
2162
signer := httpsignatures.NewSigner(
2263
httpsignatures.AlgorithmHmacSha256,
@@ -51,3 +92,28 @@ func Example_verification() {
5192
// request was signed correctly.
5293
}
5394
}
95+
96+
func Example_verificationRSA() {
97+
_ = func(w http.ResponseWriter, r *http.Request) {
98+
sig, err := httpsignatures.FromRequest(r)
99+
if err != nil {
100+
// Probably a malformed header
101+
http.Error(w, "Bad Request", http.StatusBadRequest)
102+
panic(err)
103+
}
104+
105+
// if you have headers that must be signed check
106+
// that they are in sig.Headers
107+
108+
var pemPublicKeyBytes []byte // = lookup using sig.KeyID
109+
block, _ := pem.Decode(pemPublicKeyBytes)
110+
publicKey, _ := x509.ParsePKIXPublicKey(block.Bytes)
111+
112+
if !sig.IsValidRSA(publicKey.(*rsa.PublicKey), r) {
113+
http.Error(w, "Forbidden", http.StatusForbidden)
114+
return
115+
}
116+
117+
// request was signed correctly.
118+
}
119+
}

signature.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ func (s Signature) IsValid(key string, r *http.Request) bool {
136136
return s.isValid(key, r)
137137
}
138138

139-
// IsValidRSA validates that the signature was signed by an RSA private key.
139+
// IsValidRSA validates that the request was signed by an RSA private key, using
140+
// the public key for verification. This method should only be called when the
141+
// underlying Algorithm is an RSA backed implementation.
140142
func (s Signature) IsValidRSA(key *rsa.PublicKey, r *http.Request) bool {
141143
return s.isValid(key, r)
142144
}

signer.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ func (s Signer) SignRequest(id, key string, r *http.Request) error {
4949
return s.signRequest(id, key, r)
5050
}
5151

52-
// SignRequestRSA signs a request with an RSA private key.
52+
// SignRequestRSA signs a request with an RSA private key. This method should
53+
// only be called when the underlying Algorithm is an RSA backed implementation.
5354
func (s Signer) SignRequestRSA(id string, key *rsa.PrivateKey, r *http.Request) error {
5455
return s.signRequest(id, key, r)
5556
}
@@ -67,7 +68,18 @@ func (s Signer) signRequest(keyId string, key interface{}, r *http.Request) erro
6768

6869
// AuthRequest adds a http signature to the Authorization: HTTP Header
6970
func (s Signer) AuthRequest(id, key string, r *http.Request) error {
70-
sig, err := s.buildSignature(id, key, r)
71+
return s.authRequest(id, key, r)
72+
}
73+
74+
// AuthRequestRSA adds an http signature to the Authorization: HTTP Header using
75+
// an RSA private key to generate the signature.This method should only be
76+
// called when the underlying Algorithm is an RSA backed implementation.
77+
func (s Signer) AuthRequestRSA(id string, key *rsa.PrivateKey, r *http.Request) error {
78+
return s.authRequest(id, key, r)
79+
}
80+
81+
func (s Signer) authRequest(keyId string, key interface{}, r *http.Request) error {
82+
sig, err := s.buildSignature(keyId, key, r)
7183
if err != nil {
7284
return err
7385
}

signer_test.go

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,55 @@ func TestSignHmacSha256(t *testing.T) {
5656
)
5757
}
5858

59+
func TestSignRsaSha1(t *testing.T) {
60+
r := &http.Request{
61+
Header: http.Header{
62+
"Date": []string{"Thu, 05 Jan 2012 21:31:40 GMT"},
63+
},
64+
}
65+
66+
block, _ := pem.Decode([]byte(TEST_PRIVATE_KEY))
67+
privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
68+
69+
err := DefaultRsaSha1Signer.SignRequestRSA(TEST_KEY_ID, privateKey, r)
70+
assert.Nil(t, err)
71+
72+
s, err := FromRequest(r)
73+
assert.Nil(t, err)
74+
75+
assert.Equal(t, TEST_KEY_ID, s.KeyID)
76+
77+
assert.Equal(t,
78+
"KcypPq/UJBlvY9WR/zb6pGS2vkhlzKX1OUjtImOG8d4CynptmMxXWuzi3LeJW8jOnEmjC00Ga2tOruaSDo8MuDlXEy7JrYIqqD39XYKt5pFQ7dScpZARIrQ4H0n8bn4uIQFLMxkNt2aeuDogyUPcRMxBr6mVe0OHw8MY1y5xdpQ=",
79+
s.Signature,
80+
)
81+
}
82+
83+
func TestSignRsaSha256(t *testing.T) {
84+
r := &http.Request{
85+
Header: http.Header{
86+
"Date": []string{"Thu, 05 Jan 2012 21:31:40 GMT"},
87+
},
88+
}
89+
90+
block, _ := pem.Decode([]byte(TEST_PRIVATE_KEY))
91+
privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
92+
93+
err := DefaultRsaSha256Signer.SignRequestRSA(TEST_KEY_ID, privateKey, r)
94+
assert.Nil(t, err)
95+
96+
s, err := FromRequest(r)
97+
assert.Nil(t, err)
98+
99+
assert.Equal(t, TEST_KEY_ID, s.KeyID)
100+
101+
assert.Equal(t,
102+
"TQZq1wGaOdAT3kiSOUq29jh6UG0DgZH2TW6aHYVNrHwKiACi1b9U58la/0SeDqEt6mKe836tHVKXouzNM5LaRiXWW13lZstdg/rXYxZ6N46jZKwVKRXcw9sc6/nZfjnDsxWs6/Zi4Si8hdEZx4CczUjPWBGDi+EaY+PPyZWSibs=",
103+
s.Signature,
104+
)
105+
}
106+
107+
// Tests conformance with the test cases provided in the RFC document.
59108
func TestSignRsaSha256_RFC(t *testing.T) {
60109
block, _ := pem.Decode([]byte(TEST_PRIVATE_KEY))
61110
privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
@@ -101,27 +150,6 @@ func TestSignRsaSha256_RFC(t *testing.T) {
101150
}
102151
}
103152

104-
func TestSignRsaSha256_BasicTest(t *testing.T) {
105-
r := newRFCRequest()
106-
107-
block, _ := pem.Decode([]byte(TEST_PRIVATE_KEY))
108-
privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
109-
110-
signer := NewSigner(AlgorithmRsaSha256, RequestTarget, "host", "date")
111-
err := signer.SignRequestRSA(TEST_KEY_ID, privateKey, r)
112-
assert.Nil(t, err)
113-
114-
s, err := FromRequest(r)
115-
assert.Nil(t, err)
116-
117-
assert.Equal(t, TEST_KEY_ID, s.KeyID)
118-
119-
assert.Equal(t,
120-
"HUxc9BS3P/kPhSmJo+0pQ4IsCo007vkv6bUm4Qehrx+B1Eo4Mq5/6KylET72ZpMUS80XvjlOPjKzxfeTQj4DiKbAzwJAb4HX3qX6obQTa00/qPDXlMepD2JtTw33yNnm/0xV7fQuvILN/ys+378Ysi082+4xBQFwvhNvSoVsGv4=",
121-
s.Signature,
122-
)
123-
}
124-
125153
func TestSignWithMissingDateHeader(t *testing.T) {
126154
r := &http.Request{Header: http.Header{}}
127155

0 commit comments

Comments
 (0)