|
| 1 | +import { createPrivateKey, KeyObject } from 'crypto'; |
| 2 | +import { cavage, createSigner } from '../../src'; |
| 3 | +import { expect } from 'chai'; |
| 4 | + |
| 5 | +/** |
| 6 | + * These test have been taken from the specification, but they are only accurate as of |
| 7 | + * version 10 of the specification (https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-10) |
| 8 | + * and not version 12 (the last one). As such, some of the tests have been modified to pass with the |
| 9 | + * latest implementation. |
| 10 | + */ |
| 11 | +describe('cavage', () => { |
| 12 | + describe('specification', () => { |
| 13 | + const request = { |
| 14 | + method: 'POST', |
| 15 | + url: 'https://example.com/foo?param=value&pet=dog', |
| 16 | + headers: { |
| 17 | + 'Host': 'example.com', |
| 18 | + 'Date': 'Sun, 05 Jan 2014 21:31:40 GMT', |
| 19 | + 'Content-Type': 'application/json', |
| 20 | + 'Digest': 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=', |
| 21 | + 'Content-Length': '18', |
| 22 | + }, |
| 23 | + body: '{"hello": "world"}', |
| 24 | + } |
| 25 | + let key: KeyObject; |
| 26 | + before('load rsa key', () => { |
| 27 | + key = createPrivateKey('-----BEGIN RSA PRIVATE KEY-----\n' + |
| 28 | + 'MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF\n' + |
| 29 | + 'NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F\n' + |
| 30 | + 'UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB\n' + |
| 31 | + 'AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA\n' + |
| 32 | + 'QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK\n' + |
| 33 | + 'kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg\n' + |
| 34 | + 'f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u\n' + |
| 35 | + '412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc\n' + |
| 36 | + 'mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7\n' + |
| 37 | + 'kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA\n' + |
| 38 | + 'gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW\n' + |
| 39 | + 'G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI\n' + |
| 40 | + '7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==\n' + |
| 41 | + '-----END RSA PRIVATE KEY-----') |
| 42 | + }); |
| 43 | + it('Default Test (C.1)', async () => { |
| 44 | + const signed = await cavage.signMessage({ |
| 45 | + key: createSigner(key, 'rsa-v1_5-sha256', 'Test'), |
| 46 | + fields: ['Date'], |
| 47 | + params: ['keyid', 'alg'], |
| 48 | + }, request); |
| 49 | + expect(signed.headers).to.have.property('Signature', 'keyId="Test",algorithm="rsa-sha256",' + |
| 50 | + 'headers="date",' + // NB: Not present in specificaiton example |
| 51 | + 'signature="SjWJWbWN7i0wzBvtPl8rbASWz5xQW6mcJmn+ibttBqtifLN7Sazz' + |
| 52 | + '6m79cNfwwb8DMJ5cou1s7uEGKKCs+FLEEaDV5lp7q25WqS+lavg7T8hc0GppauB' + |
| 53 | + '6hbgEKTwblDHYGEtbGmtdHgVCk9SuS13F0hZ8FD0k/5OxEPXe5WozsbM="'); |
| 54 | + }); |
| 55 | + it('Basic Test (C.2)', async () => { |
| 56 | + const signed = await cavage.signMessage({ |
| 57 | + key: createSigner(key, 'rsa-v1_5-sha256', 'Test'), |
| 58 | + params: ['keyid', 'alg'], |
| 59 | + fields: ['@request-target', 'host', 'date'], |
| 60 | + }, request); |
| 61 | + expect(signed.headers).to.have.property('Signature', 'keyId="Test",algorithm="rsa-sha256",' + |
| 62 | + 'headers="(request-target) host date",' + |
| 63 | + 'signature="qdx+H7PHHDZgy4y/Ahn9Tny9V3GP6YgBPyUXMmoxWtLbHpUnXS' + |
| 64 | + '2mg2+SbrQDMCJypxBLSPQR2aAjn7ndmw2iicw3HMbe8VfEdKFYRqzic+efkb3' + |
| 65 | + 'nndiv/x1xSHDJWeSWkx3ButlYSuBskLu6kd9Fswtemr3lgdDEmn04swr2Os0="'); |
| 66 | + }); |
| 67 | + it('All Headers Test (C.3)', async () => { |
| 68 | + const signed = await cavage.signMessage({ |
| 69 | + key: createSigner(key, 'rsa-v1_5-sha256', 'Test'), |
| 70 | + params: ['keyid', 'alg', 'created', 'expires'], |
| 71 | + paramValues: { |
| 72 | + created: new Date(1402170695000), |
| 73 | + expires: new Date(1402170699000), |
| 74 | + }, |
| 75 | + fields: ['@request-target', 'host', 'date', 'content-type', 'digest', 'content-length'], |
| 76 | + }, request); |
| 77 | + // NB: As noted in the spec, some of the test "vectors" are wrong. For this test, the signature has been |
| 78 | + // calculated without the (created) and (expires) params being included in the signature despite the example |
| 79 | + // showing they are in the signature header |
| 80 | + expect(signed.headers).to.have.property('Signature', 'keyId="Test",algorithm="rsa-sha256",' + |
| 81 | + 'created=1402170695,expires=1402170699,' + |
| 82 | + // 'headers="(request-target) (created) (expires) ' + |
| 83 | + 'headers="(request-target) ' + // NB: the example signature has only been computed over request-target |
| 84 | + 'host date content-type digest content-length",' + |
| 85 | + 'signature="vSdrb+dS3EceC9bcwHSo4MlyKS59iFIrhgYkz8+oVLEEzmYZZvRs' + |
| 86 | + '8rgOp+63LEM3v+MFHB32NfpB2bEKBIvB1q52LaEUHFv120V01IL+TAD48XaERZF' + |
| 87 | + 'ukWgHoBTLMhYS2Gb51gWxpeIq8knRmPnYePbF5MOkR0Zkly4zKH7s1dE="'); |
| 88 | + }); |
| 89 | + }); |
| 90 | +}); |
0 commit comments