diff --git a/src/utils/index.ts b/src/utils/index.ts index ea45e33..5be573e 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -46,7 +46,7 @@ const generateSecret = (secretLength: number | HMACAlgorithm) => { * @param data Buffer to convert to base32 * @returns string which is the base32 encoding of the buffer */ -const convertBase32 = (data: Buffer) => { +const convertToBase32 = (data: Buffer) => { const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' let bits = 0 let value = 0 @@ -68,6 +68,24 @@ const convertBase32 = (data: Buffer) => { return output } +const base32ToBuffer = (input: string) => { + const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' + let bits = 0 + let value = 0 + let index = 0 + const output = Buffer.alloc(Math.ceil((input.length * 5) / 8)) + for (let i = 0; i < input.length; i++) { + value = (value << 5) | alphabet.indexOf(input[i].toUpperCase()) + bits += 5 + + if (bits >= 8) { + output.writeUInt8((value >>> (bits - 8)) & 255, index++) + bits -= 8 + } + } + return output +} + interface URIMakerFunction { ( secret: Buffer, @@ -118,7 +136,7 @@ const generateURI: URIMakerFunction = ( Object.entries({ ...options, ...params, - secret: convertBase32(secret), + secret: convertToBase32(secret), }).forEach(([key, value]) => result.searchParams.append(key, value.toString()) ) @@ -131,4 +149,6 @@ export { generateURI, URItype, generateSecret, + convertToBase32, + base32ToBuffer, } diff --git a/test/utils.test.ts b/test/utils.test.ts index b7048e8..5efd1f9 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -1,5 +1,11 @@ import { expect } from 'chai' -import { HMACAlgorithm, URItype, generateURI } from '../src/utils' +import { + HMACAlgorithm, + URItype, + base32ToBuffer, + convertToBase32, + generateURI, +} from '../src/utils' describe('URI Generation', () => { it('should generate URI', () => { @@ -26,3 +32,14 @@ describe('URI Generation', () => { expect(uri.searchParams.get('secret')).to.equal('JBSWY3DPEHPK3PXP') }) }) + +describe('Base32 conversion', () => { + it('should convert to base32', () => { + const originalData = [ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0xde, 0xad, 0xbe, 0xef, + ] + const base32 = convertToBase32(Buffer.from(originalData)) + const backToBuffer = base32ToBuffer(base32) + expect([...backToBuffer]).to.deep.equal(originalData) + }) +})