-
Notifications
You must be signed in to change notification settings - Fork 388
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: pad base64 strings for base64js (#722)
* fix: pad base64 strings for base64js * really test signer for Node
- Loading branch information
1 parent
e53acfb
commit 81e0a23
Showing
4 changed files
with
178 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import * as base64js from 'base64-js'; | ||
import {assert} from 'chai'; | ||
import {createCrypto} from '../src/crypto/crypto'; | ||
import {BrowserCrypto} from '../src/crypto/browser/crypto'; | ||
|
||
// The following public key was copied from JWK RFC 7517: | ||
// https://tools.ietf.org/html/rfc7517 | ||
// The private key used for signing the test message below was taken from the same RFC. | ||
const publicKey = { | ||
kty: 'RSA', | ||
n: | ||
'0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw', | ||
e: 'AQAB', | ||
alg: 'RS256', | ||
kid: '2011-04-29', | ||
}; | ||
|
||
// Not all browsers support `TextEncoder`. The following `require` will | ||
// provide a fast UTF8-only replacement for those browsers that don't support | ||
// text encoding natively. | ||
require('fast-text-encoding'); | ||
|
||
describe('Browser crypto tests', () => { | ||
const crypto = createCrypto(); | ||
|
||
it('should create a BrowserCrypto instance', () => { | ||
assert(crypto instanceof BrowserCrypto); | ||
}); | ||
|
||
it('should calculate SHA256 digest', async () => { | ||
const input = 'I can calculate SHA256'; | ||
const expectedDigest = 'c9CEhti/1PtLwS3YkDYE3b3lrZW276VnvXI86BqIESI='; | ||
const calculatedDigest = await crypto.sha256DigestBase64(input); | ||
assert.strictEqual(calculatedDigest, expectedDigest); | ||
}); | ||
|
||
it('should generate random bytes', () => { | ||
const requestedLength = 20; | ||
const generated1Base64 = crypto.randomBytesBase64(requestedLength); | ||
const generated1 = base64js.toByteArray(generated1Base64); | ||
assert.strictEqual(generated1.length, requestedLength); | ||
const generated2Base64 = crypto.randomBytesBase64(requestedLength); | ||
const generated2 = base64js.toByteArray(generated2Base64); | ||
assert.strictEqual(generated2.length, requestedLength); | ||
// random strings are random! let's just check they are different. | ||
// if they are the same, we have a problem. | ||
assert.notStrictEqual(generated1Base64, generated2Base64); | ||
}); | ||
|
||
it('should verify a signature', async () => { | ||
const message = 'This message is signed'; | ||
const signatureBase64 = [ | ||
'BE1qD48LdssePdMmOhcanOd8V+i4yLSOL0H2EXNyy', | ||
'lCePnldIsLVqrOJnVkd0MUKxS/Y9B0te2tqlS8psP', | ||
'j9IWjcpiQeT9wUDRadxHIX26W6JHgSCOzOavpJCbh', | ||
'M3Kez7QEwbkrI54rYu7qgx/mmckxkC0vhg0Z5OQbO', | ||
'IXfILVs1ztNNdt9r/ZzNVxTMKhL3nHLfjVqG/LUGy', | ||
'RhFhjzLvIJAfL0CSEfycUvm6t5NVzF4SkZ8KKQ7wJ', | ||
'vLw492bRB/633GJOZ1prVjAUQUI64BXFrvRgWsxLK', | ||
'M0XtF5tNbC+eIDrH0LiMraAhcZwj1iWofH1h/dg3E', | ||
'xtU9UWfbed/yfw', | ||
].join(''); // note: no padding | ||
const verified = await crypto.verify(publicKey, message, signatureBase64); | ||
assert(verified); | ||
}); | ||
|
||
it('should not createSign', () => { | ||
assert.throws(() => { | ||
crypto.createSign('never worked'); | ||
}); | ||
}); | ||
|
||
it('should decode unpadded base64', () => { | ||
const originalString = 'test string'; | ||
const base64String = 'dGVzdCBzdHJpbmc'; | ||
const decodedString = crypto.decodeBase64StringUtf8(base64String); | ||
assert.strictEqual(decodedString, originalString); | ||
}); | ||
|
||
it('should encode to base64 and pad the result', () => { | ||
const originalString = 'test string'; | ||
const base64String = 'dGVzdCBzdHJpbmc='; | ||
const encodedString = crypto.encodeBase64StringUtf8(originalString); | ||
assert.strictEqual(encodedString, base64String); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import * as nativeCrypto from 'crypto'; | ||
import * as fs from 'fs'; | ||
import {assert} from 'chai'; | ||
import {createCrypto} from '../src/crypto/crypto'; | ||
import {NodeCrypto} from '../src/crypto/node/crypto'; | ||
|
||
const publicKey = fs.readFileSync('./test/fixtures/public.pem', 'utf-8'); | ||
const privateKey = fs.readFileSync('./test/fixtures/private.pem', 'utf-8'); | ||
|
||
describe('Node.js crypto tests', () => { | ||
const crypto = createCrypto(); | ||
|
||
it('should create a NodeCrypto instance', () => { | ||
assert(crypto instanceof NodeCrypto); | ||
}); | ||
|
||
it('should calculate SHA256 digest', async () => { | ||
const input = 'I can calculate SHA256'; | ||
const expectedDigest = 'c9CEhti/1PtLwS3YkDYE3b3lrZW276VnvXI86BqIESI='; | ||
const calculatedDigest = await crypto.sha256DigestBase64(input); | ||
assert.strictEqual(calculatedDigest, expectedDigest); | ||
}); | ||
|
||
it('should generate random bytes', () => { | ||
const requestedLength = 20; | ||
const generated1Base64 = crypto.randomBytesBase64(requestedLength); | ||
const generated1 = Buffer.from(generated1Base64, 'base64'); | ||
assert.strictEqual(generated1.length, requestedLength); | ||
const generated2Base64 = crypto.randomBytesBase64(requestedLength); | ||
const generated2 = Buffer.from(generated2Base64, 'base64'); | ||
assert.strictEqual(generated2.length, requestedLength); | ||
// random strings are random! let's just check they are different. | ||
// if they are the same, we have a problem. | ||
assert.notStrictEqual(generated1Base64, generated2Base64); | ||
}); | ||
|
||
it('should verify a signature', async () => { | ||
const message = 'This message is signed'; | ||
const signatureBase64 = [ | ||
'ufyKBV+Ar7Yq8CSmSIN9m38ch4xnWBz8CP4qHh6V+', | ||
'm4cCbeXdR1MEmWVhNJjZQFv3KL3tDAnl0Q4bTcSR/', | ||
'mmhXaRjdxyJ6xAUp0KcbVq6xsDIbnnYHSgYr3zVoS', | ||
'dRRefWSWTknN1S69fNmKEfUeBIJA93xitr3pbqtLC', | ||
'bP28XNU', | ||
].join(''); // note: no padding | ||
const verified = await crypto.verify(publicKey, message, signatureBase64); | ||
assert(verified); | ||
}); | ||
|
||
it('should create a signer that works', () => { | ||
const message = 'This message is signed'; | ||
const expectedSignatureBase64 = [ | ||
'ufyKBV+Ar7Yq8CSmSIN9m38ch4xnWBz8CP4qHh6V+', | ||
'm4cCbeXdR1MEmWVhNJjZQFv3KL3tDAnl0Q4bTcSR/', | ||
'mmhXaRjdxyJ6xAUp0KcbVq6xsDIbnnYHSgYr3zVoS', | ||
'dRRefWSWTknN1S69fNmKEfUeBIJA93xitr3pbqtLC', | ||
'bP28XNU=', | ||
].join(''); | ||
|
||
const signer = crypto.createSign('SHA256'); | ||
assert(signer); | ||
signer.update(message); | ||
const signatureBase64 = signer.sign(privateKey, 'base64'); | ||
assert.strictEqual(signatureBase64, expectedSignatureBase64); | ||
}); | ||
|
||
it('should decode unpadded base64', () => { | ||
const originalString = 'test string'; | ||
const base64String = 'dGVzdCBzdHJpbmc'; | ||
const decodedString = crypto.decodeBase64StringUtf8(base64String); | ||
assert.strictEqual(decodedString, originalString); | ||
}); | ||
|
||
it('should encode to base64 and pad the result', () => { | ||
const originalString = 'test string'; | ||
const base64String = 'dGVzdCBzdHJpbmc='; | ||
const encodedString = crypto.encodeBase64StringUtf8(originalString); | ||
assert.strictEqual(encodedString, base64String); | ||
}); | ||
}); |