Skip to content

Commit bd286b0

Browse files
committed
Update CF CookieSigner to use crypto.Signer interface
CloudFront CookieSigner uses *rsa.PrivateKey, but CloudFront supports ECDSA since 2025. To support ECDSA, this commit makes CookieSigner accept crypto.Signer, including *rsa.PrivateKey and *ecdsa.PrivateKey. For CF URLSigner, the same change was done by bedf94c.
1 parent 09ac115 commit bd286b0

2 files changed

Lines changed: 40 additions & 17 deletions

File tree

feature/cloudfront/sign/sign_cookie.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package sign
22

33
import (
4-
"crypto/rsa"
4+
"crypto"
55
"fmt"
66
"net/http"
77
"strings"
@@ -55,22 +55,20 @@ func (o CookieOptions) apply(opts ...func(*CookieOptions)) CookieOptions {
5555
// The signer is safe to use concurrently, but the optional cookies options
5656
// are not safe to modify concurrently.
5757
type CookieSigner struct {
58-
keyID string
59-
privKey *rsa.PrivateKey
58+
keyID string
59+
signer crypto.Signer
6060

6161
Opts CookieOptions
6262
}
6363

6464
// NewCookieSigner constructs and returns a new CookieSigner to be used to for
6565
// signing Amazon CloudFront URL resources with.
66-
func NewCookieSigner(keyID string, privKey *rsa.PrivateKey, opts ...func(*CookieOptions)) *CookieSigner {
67-
signer := &CookieSigner{
68-
keyID: keyID,
69-
privKey: privKey,
70-
Opts: CookieOptions{}.apply(opts...),
66+
func NewCookieSigner(keyID string, signer crypto.Signer, opts ...func(*CookieOptions)) *CookieSigner {
67+
return &CookieSigner{
68+
keyID: keyID,
69+
signer: signer,
70+
Opts: CookieOptions{}.apply(opts...),
7171
}
72-
73-
return signer
7472
}
7573

7674
// Sign returns the cookies needed to allow user agents to make arbetrary
@@ -84,7 +82,7 @@ func NewCookieSigner(keyID string, privKey *rsa.PrivateKey, opts ...func(*Cookie
8482
//
8583
// Example:
8684
//
87-
// s := sign.NewCookieSigner(keyID, privKey)
85+
// s := sign.NewCookieSigner(keyID, signer)
8886
//
8987
// // Get Signed cookies for a resource that will expire in 1 hour
9088
// cookies, err := s.Sign("*", time.Now().Add(1 * time.Hour))
@@ -127,7 +125,7 @@ func (s CookieSigner) Sign(u string, expires time.Time, opts ...func(*CookieOpti
127125
}
128126

129127
p := NewCannedPolicy(resource, expires)
130-
return createCookies(p, s.keyID, s.privKey, s.Opts.apply(opts...))
128+
return createCookies(p, s.keyID, s.signer, s.Opts.apply(opts...))
131129
}
132130

133131
// Returns and validates the URL's scheme.
@@ -154,7 +152,7 @@ func cookieURLScheme(u string) (string, error) {
154152
//
155153
// Example:
156154
//
157-
// s := sign.NewCookieSigner(keyID, privKey)
155+
// s := sign.NewCookieSigner(keyID, signer)
158156
//
159157
// policy := &sign.Policy{
160158
// Statements: []sign.Statement{
@@ -204,13 +202,13 @@ func cookieURLScheme(u string) (string, error) {
204202
// }
205203
// }
206204
func (s CookieSigner) SignWithPolicy(p *Policy, opts ...func(*CookieOptions)) ([]*http.Cookie, error) {
207-
return createCookies(p, s.keyID, s.privKey, s.Opts.apply(opts...))
205+
return createCookies(p, s.keyID, s.signer, s.Opts.apply(opts...))
208206
}
209207

210208
// Prepares the cookies to be attached to the header. An (optional) options
211209
// struct is provided in case people don't want to manually edit their cookies.
212-
func createCookies(p *Policy, keyID string, privKey *rsa.PrivateKey, opt CookieOptions) ([]*http.Cookie, error) {
213-
b64Sig, b64Policy, err := p.Sign(privKey)
210+
func createCookies(p *Policy, keyID string, signer crypto.Signer, opt CookieOptions) ([]*http.Cookie, error) {
211+
b64Sig, b64Policy, err := p.Sign(signer)
214212
if err != nil {
215213
return nil, err
216214
}

feature/cloudfront/sign/sign_cookie_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package sign
22

33
import (
4+
"crypto/ecdsa"
5+
"crypto/elliptic"
46
"crypto/rsa"
57
"testing"
68
"time"
@@ -16,7 +18,7 @@ func TestNewCookieSigner(t *testing.T) {
1618
if e, a := "keyID", signer.keyID; e != a {
1719
t.Errorf("expect %v, got %v", e, a)
1820
}
19-
if e, a := privKey, signer.privKey; e != a {
21+
if e, a := privKey, signer.signer; e != a {
2022
t.Errorf("expect %v, got %v", e, a)
2123
}
2224
}
@@ -119,3 +121,26 @@ func TestSignCookie_WithCookieOptions(t *testing.T) {
119121
}
120122
}
121123
}
124+
125+
func TestSignCookie_ECDSA(t *testing.T) {
126+
privKey, err := ecdsa.GenerateKey(elliptic.P256(), randReader)
127+
if err != nil {
128+
t.Errorf("expect no error, got %v", err)
129+
}
130+
131+
signer := NewCookieSigner("keyID", privKey)
132+
cookies, err := signer.Sign("http*://*", time.Now().Add(1*time.Hour))
133+
134+
if err != nil {
135+
t.Errorf("expect no error, got %v", err)
136+
}
137+
if e, a := CookiePolicyName, cookies[0].Name; e != a {
138+
t.Errorf("expect %v, got %v", e, a)
139+
}
140+
if e, a := CookieSignatureName, cookies[1].Name; e != a {
141+
t.Errorf("expect %v, got %v", e, a)
142+
}
143+
if e, a := CookieKeyIDName, cookies[2].Name; e != a {
144+
t.Errorf("expect %v, got %v", e, a)
145+
}
146+
}

0 commit comments

Comments
 (0)