@@ -46,17 +46,21 @@ function createSignature(data: string): string {
4646 signer . update ( data ) ;
4747 return normalizeBase64 ( signer . sign ( privateKey , "base64" ) ) ;
4848}
49+
4950function verifySignature ( signature : string , data : string ) : boolean {
5051 const verifier = createVerify ( "RSA-SHA1" ) ;
5152 verifier . update ( data ) ;
5253 return verifier . verify ( privateKey , signature , "base64" ) ;
5354}
55+
5456function encodeToBase64 ( str : string ) : string {
5557 return normalizeBase64 ( Buffer . from ( str ) . toString ( "base64" ) ) ;
5658}
59+
5760function normalizeBase64 ( str : string ) : string {
5861 return str . replace ( / \+ / g, "-" ) . replace ( / = / g, "_" ) . replace ( / \/ / g, "~" ) ;
5962}
63+
6064function denormalizeBase64 ( str : string ) : string {
6165 return str . replace ( / \- / g, "+" ) . replace ( / _ / g, "=" ) . replace ( / ~ / g, "/" ) ;
6266}
@@ -78,6 +82,7 @@ describe("getSignedUrl", () => {
7882 }
7983 expect ( result . query [ "foo" ] ) . toBe ( "bar &=; baz" ) ;
8084 } ) ;
85+
8186 it ( "should include url path in policy of signed URL" , ( ) => {
8287 const url = "https://example.com/private.jpeg?foo=bar" ;
8388 const result = parseUrl (
@@ -108,6 +113,7 @@ describe("getSignedUrl", () => {
108113 } ) ;
109114 expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
110115 } ) ;
116+
111117 it ( "should sign a URL with a canned policy" , ( ) => {
112118 const result = getSignedUrl ( {
113119 url,
@@ -135,6 +141,7 @@ describe("getSignedUrl", () => {
135141 const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
136142 expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
137143 } ) ;
144+
138145 it ( "should sign a URL with a custom policy containing a start date" , ( ) => {
139146 const result = getSignedUrl ( {
140147 url,
@@ -166,6 +173,7 @@ describe("getSignedUrl", () => {
166173 const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
167174 expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
168175 } ) ;
176+
169177 it ( "should sign a URL with a custom policy containing an ip address" , ( ) => {
170178 const result = getSignedUrl ( {
171179 url,
@@ -197,6 +205,7 @@ describe("getSignedUrl", () => {
197205 const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
198206 expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
199207 } ) ;
208+
200209 it ( "should sign a URL with a custom policy containing a start date and ip address" , ( ) => {
201210 const result = getSignedUrl ( {
202211 url,
@@ -232,6 +241,7 @@ describe("getSignedUrl", () => {
232241 const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
233242 expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
234243 } ) ;
244+
235245 it ( "should allow an ip address with and without a mask" , ( ) => {
236246 const baseArgs = {
237247 url,
@@ -253,6 +263,7 @@ describe("getSignedUrl", () => {
253263 } )
254264 ) . toBeTruthy ( ) ;
255265 } ) ;
266+
256267 it ( "should throw an error when the ip address is invalid" , ( ) => {
257268 const baseArgs = {
258269 url,
@@ -298,6 +309,7 @@ describe("getSignedUrl", () => {
298309 } )
299310 ) . toThrow ( 'IP address "10.0.0.256" is invalid due to invalid IP octets.' ) ;
300311 } ) ;
312+
301313 it ( "should sign a RTMP URL" , ( ) => {
302314 const url = "rtmp://d111111abcdef8.cloudfront.net/private-content/private.jpeg" ;
303315 const result = getSignedUrl ( {
@@ -325,6 +337,7 @@ describe("getSignedUrl", () => {
325337 ) ;
326338 expect ( verifySignature ( denormalizeBase64 ( signature ) , policyStr ) ) . toBeTruthy ( ) ;
327339 } ) ;
340+
328341 it ( "should sign a URL with a policy provided by the user" , ( ) => {
329342 const policy = '{"foo":"bar"}' ;
330343 const result = getSignedUrl ( {
@@ -339,6 +352,7 @@ describe("getSignedUrl", () => {
339352 const signatureQueryParam = denormalizeBase64 ( signature ) ;
340353 expect ( verifySignature ( signatureQueryParam , policy ) ) . toBeTruthy ( ) ;
341354 } ) ;
355+
342356 it ( "should sign a URL automatically extracted from a policy provided by the user" , ( ) => {
343357 const policy = JSON . stringify ( { Statement : [ { Resource : url } ] } ) ;
344358 const result = getSignedUrl ( {
@@ -376,6 +390,7 @@ describe("getSignedCookies", () => {
376390 } )
377391 ) . toBeTruthy ( ) ;
378392 } ) ;
393+
379394 it ( "should throw an error when the ip address is invalid" , ( ) => {
380395 const baseArgs = {
381396 url,
@@ -421,6 +436,7 @@ describe("getSignedCookies", () => {
421436 } )
422437 ) . toThrow ( 'IP address "10.0.0.256" is invalid due to invalid IP octets.' ) ;
423438 } ) ;
439+
424440 it ( "should be able sign cookies that contain a URL with wildcards" , ( ) => {
425441 const url = "https://example.com/private-content/*" ;
426442 const result = getSignedCookies ( {
@@ -444,6 +460,7 @@ describe("getSignedCookies", () => {
444460 } ) ;
445461 expect ( verifySignature ( denormalizeBase64 ( result [ "CloudFront-Signature" ] ) , policyStr ) ) . toBeTruthy ( ) ;
446462 } ) ;
463+
447464 it ( "should sign cookies with a canned policy" , ( ) => {
448465 const result = getSignedCookies ( {
449466 url,
@@ -475,6 +492,7 @@ describe("getSignedCookies", () => {
475492 expect ( result [ "CloudFront-Signature" ] ) . toBe ( expected [ "CloudFront-Signature" ] ) ;
476493 expect ( verifySignature ( denormalizeBase64 ( result [ "CloudFront-Signature" ] ) , policyStr ) ) . toBeTruthy ( ) ;
477494 } ) ;
495+
478496 it ( "should sign cookies with a custom policy containing a start date" , ( ) => {
479497 const result = getSignedCookies ( {
480498 url,
@@ -510,6 +528,7 @@ describe("getSignedCookies", () => {
510528 expect ( result [ "CloudFront-Signature" ] ) . toBe ( expected [ "CloudFront-Signature" ] ) ;
511529 expect ( verifySignature ( denormalizeBase64 ( result [ "CloudFront-Signature" ] ) , policyStr ) ) . toBeTruthy ( ) ;
512530 } ) ;
531+
513532 it ( "should sign cookies with a custom policy containing an ip address" , ( ) => {
514533 const result = getSignedCookies ( {
515534 url,
@@ -545,6 +564,7 @@ describe("getSignedCookies", () => {
545564 expect ( result [ "CloudFront-Signature" ] ) . toBe ( expected [ "CloudFront-Signature" ] ) ;
546565 expect ( verifySignature ( denormalizeBase64 ( result [ "CloudFront-Signature" ] ) , policyStr ) ) . toBeTruthy ( ) ;
547566 } ) ;
567+
548568 it ( "should sign cookies with a custom policy containing a start date and ip address" , ( ) => {
549569 const result = getSignedCookies ( {
550570 url,
@@ -584,6 +604,7 @@ describe("getSignedCookies", () => {
584604 expect ( result [ "CloudFront-Signature" ] ) . toBe ( expected [ "CloudFront-Signature" ] ) ;
585605 expect ( verifySignature ( denormalizeBase64 ( result [ "CloudFront-Signature" ] ) , policyStr ) ) . toBeTruthy ( ) ;
586606 } ) ;
607+
587608 it ( "should sign cookies with a policy provided by the user without a url" , ( ) => {
588609 const policy = '{"foo":"bar"}' ;
589610 const result = getSignedCookies ( {
@@ -612,6 +633,7 @@ describe("getSignedUrl- when signing a URL with a date range", () => {
612633 const dateGreaterThanNumber = 1716034245000 ;
613634 const dateObject = new Date ( dateString ) ;
614635 const dateGreaterThanObject = new Date ( dateGreaterThanString ) ;
636+
615637 it ( "allows string input compatible with Date constructor" , ( ) => {
616638 const epochDateLessThan = Math . round ( new Date ( dateString ) . getTime ( ) / 1000 ) ;
617639 const resultUrl = getSignedUrl ( {
@@ -653,6 +675,7 @@ describe("getSignedUrl- when signing a URL with a date range", () => {
653675 expect ( resultUrl ) . toContain ( `Expires=${ epochDateLessThan } ` ) ;
654676 expect ( resultCookies [ "CloudFront-Expires" ] ) . toBe ( epochDateLessThan ) ;
655677 } ) ;
678+
656679 it ( "allows Date object input" , ( ) => {
657680 const epochDateLessThan = Math . round ( dateObject . getTime ( ) / 1000 ) ;
658681 const resultUrl = getSignedUrl ( {
@@ -673,6 +696,7 @@ describe("getSignedUrl- when signing a URL with a date range", () => {
673696 expect ( resultUrl ) . toContain ( `Expires=${ epochDateLessThan } ` ) ;
674697 expect ( resultCookies [ "CloudFront-Expires" ] ) . toBe ( epochDateLessThan ) ;
675698 } ) ;
699+
676700 it ( "allows string input for date range" , ( ) => {
677701 const result = getSignedUrl ( {
678702 url,
@@ -736,6 +760,7 @@ describe("getSignedUrl- when signing a URL with a date range", () => {
736760 const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
737761 expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
738762 } ) ;
763+
739764 it ( "allows Date object input for date range" , ( ) => {
740765 const result = getSignedUrl ( {
741766 url,
0 commit comments