Skip to content

Commit 7e0ba72

Browse files
authored
salt hash with base64 string (#179)
1 parent 22d6a1c commit 7e0ba72

File tree

4 files changed

+21
-38
lines changed

4 files changed

+21
-38
lines changed

src/client/eppo-client.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,23 +259,23 @@ describe('EppoClient E2E test', () => {
259259
expect(precomputedResponse.salt).toEqual('BzURTg==');
260260

261261
const precomputedFlags = precomputedResponse?.flags ?? {};
262-
expect(Object.keys(precomputedFlags)).toContain('34863af2a6019c80e054c6997241b3d5'); // flagKey, md5 hashed
263-
expect(Object.keys(precomputedFlags)).toContain('076aaf100f76cb2f93205dc6cd05f756'); // 'anotherFlag', md5 hashed
262+
expect(Object.keys(precomputedFlags)).toContain('61b6df4b153fdc8ee4498a008d0e40dc'); // flagKey, md5 hashed
263+
expect(Object.keys(precomputedFlags)).toContain('23ade17a2c18c4c3b8c9f780dca19fc1'); // 'anotherFlag', md5 hashed
264264

265265
const decodedFirstFlag = decodePrecomputedFlag(
266-
precomputedFlags['34863af2a6019c80e054c6997241b3d5'],
266+
precomputedFlags['61b6df4b153fdc8ee4498a008d0e40dc'],
267267
);
268-
expect(decodedFirstFlag.flagKey).toEqual('34863af2a6019c80e054c6997241b3d5');
268+
expect(decodedFirstFlag.flagKey).toEqual('61b6df4b153fdc8ee4498a008d0e40dc');
269269
expect(decodedFirstFlag.variationType).toEqual(VariationType.STRING);
270270
expect(decodedFirstFlag.variationKey).toEqual('a');
271271
expect(decodedFirstFlag.variationValue).toEqual('variation-a');
272272
expect(decodedFirstFlag.doLog).toEqual(true);
273273
expect(decodedFirstFlag.extraLogging).toEqual({});
274274

275275
const decodedSecondFlag = decodePrecomputedFlag(
276-
precomputedFlags['076aaf100f76cb2f93205dc6cd05f756'],
276+
precomputedFlags['23ade17a2c18c4c3b8c9f780dca19fc1'],
277277
);
278-
expect(decodedSecondFlag.flagKey).toEqual('076aaf100f76cb2f93205dc6cd05f756');
278+
expect(decodedSecondFlag.flagKey).toEqual('23ade17a2c18c4c3b8c9f780dca19fc1');
279279
expect(decodedSecondFlag.variationType).toEqual(VariationType.STRING);
280280
expect(decodedSecondFlag.variationKey).toEqual('b');
281281
expect(decodedSecondFlag.variationValue).toEqual('variation-b');

src/configuration.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Environment, FormatEnum, PrecomputedFlag } from './interfaces';
2-
import { generateSalt, obfuscatePrecomputedFlags, ISalt } from './obfuscation';
2+
import { generateSalt, obfuscatePrecomputedFlags } from './obfuscation';
33
import { ContextAttributes } from './types';
44

55
export interface IPrecomputedConfigurationResponse {
@@ -47,23 +47,22 @@ export class PrecomputedConfiguration implements IPrecomputedConfiguration {
4747
export class ObfuscatedPrecomputedConfiguration implements IPrecomputedConfiguration {
4848
readonly format = FormatEnum.PRECOMPUTED;
4949
readonly response: string;
50-
private saltBase: ISalt;
5150

5251
constructor(
5352
readonly subjectKey: string,
5453
flags: Record<string, PrecomputedFlag>,
5554
readonly subjectAttributes?: ContextAttributes,
5655
environment?: Environment,
5756
) {
58-
this.saltBase = generateSalt();
57+
const salt = generateSalt();
5958

6059
const precomputedResponse: IPrecomputedConfigurationResponse = {
6160
format: FormatEnum.PRECOMPUTED,
6261
obfuscated: true,
63-
salt: this.saltBase.base64String,
62+
salt,
6463
createdAt: new Date().toISOString(),
6564
environment,
66-
flags: obfuscatePrecomputedFlags(this.saltBase.saltString, flags),
65+
flags: obfuscatePrecomputedFlags(salt, flags),
6766
};
6867
this.response = JSON.stringify(precomputedResponse);
6968
}

src/obfuscation.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { decodeBase64, encodeBase64, Salt } from './obfuscation';
1+
import { decodeBase64, encodeBase64, generateSalt, setSaltOverrideForTests } from './obfuscation';
22

33
describe('obfuscation', () => {
44
it('encodes strings to base64', () => {
@@ -18,12 +18,12 @@ describe('obfuscation', () => {
1818
});
1919

2020
describe('salt', () => {
21-
it('converts from bytes to string and base64 string', () => {
21+
it('converts from bytes to base64 string', () => {
2222
const chars = new Uint8Array([101, 112, 112, 111]); // eppo
23-
const eppoSalt = new Salt(chars);
23+
setSaltOverrideForTests(chars);
2424

25-
expect(eppoSalt.saltString).toEqual('eppo');
26-
expect(eppoSalt.base64String).toEqual('ZXBwbw==');
25+
const salt64 = generateSalt();
26+
expect(salt64).toEqual('ZXBwbw==');
2727
});
2828
});
2929
});

src/obfuscation.ts

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,13 @@ export function obfuscatePrecomputedFlags(
4343
return response;
4444
}
4545

46-
export interface ISalt {
47-
saltString: string;
48-
base64String: string;
49-
bytes: Uint8Array;
50-
}
51-
52-
export class Salt implements ISalt {
53-
public readonly saltString: string;
54-
public readonly base64String: string;
55-
constructor(public readonly bytes: Uint8Array) {
56-
this.saltString = String.fromCharCode(...bytes);
57-
this.base64String = encodeBase64(this.saltString);
58-
}
59-
}
60-
61-
let _saltOverride: ISalt | null = null;
46+
let saltOverrideBytes: Uint8Array | null;
6247
export function setSaltOverrideForTests(salt: Uint8Array | null) {
63-
_saltOverride = salt ? new Salt(salt) : null;
48+
saltOverrideBytes = salt ? salt : null;
6449
}
6550

66-
export function generateSalt(length = 16): ISalt {
67-
if (_saltOverride) return _saltOverride;
68-
const array = new Uint8Array(length);
69-
crypto.getRandomValues(array);
70-
return new Salt(array);
51+
export function generateSalt(length = 16): string {
52+
return base64.fromUint8Array(
53+
saltOverrideBytes ? saltOverrideBytes : crypto.getRandomValues(new Uint8Array(length)),
54+
);
7155
}

0 commit comments

Comments
 (0)