-
Notifications
You must be signed in to change notification settings - Fork 376
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update ODIS SDK to accept any type of identifier (#9985)
* wip * general identifier odis sdk * update tests * add fn back in for backwards compatability * no salt only pepper * fix tests * rename identifiers * fix tests * PR comments * Merge branch 'master' of github.com:celo-org/celo-monorepo into isabellewei/allIdentifiers * update test * get rid of erroneously committed file * add prefix when blinding * add backwards compatibility test and fix existing tests * update dependency graph * add comment * PR comments * PR comments * ensure backwards compatibility * update dep graph * hardcode expected values in backwards compatibility test * nit: remove newline Co-authored-by: Victor Graf <victor@clabs.co> * make comments TSDoc compatible Co-authored-by: Victor Graf <victor@clabs.co> * PR comments * update docstrings and enforce prefix type * add yarn.lock * revert identity pkg version in attestation-service * use latest identity pkg version pre identifier change in attestation-service * yarn.lock * update test value for nested hashing Co-authored-by: Victor Graf <victor@clabs.co> Co-authored-by: Alec Schaefer <alec@cLabs.co>
- Loading branch information
1 parent
80a7390
commit 4041432
Showing
8 changed files
with
736 additions
and
94 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
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
117 changes: 117 additions & 0 deletions
117
packages/sdk/identity/src/odis/identifier-backwards-compatibility.test.ts
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,117 @@ | ||
import { getPhoneHash } from '@celo/base' | ||
import { soliditySha3 } from '@celo/utils/lib/solidity' | ||
import { OdisUtils } from 'old-identity-sdk' | ||
import { WasmBlsBlindingClient } from './bls-blinding-client' | ||
import { | ||
getBlindedIdentifier, | ||
getIdentifierHash, | ||
getObfuscatedIdentifier, | ||
IdentifierPrefix, | ||
} from './identifier' | ||
import { AuthenticationMethod, AuthSigner, getServiceContext } from './query' | ||
|
||
const mockE164Number = '+14155550000' | ||
const mockAccount = '0x755dB5fF7B82e9a96e0dDDD143293dc2ADeC0050' | ||
// const mockPrivateKey = '0x2cacaf965ae80da49d5b1fc4b4c9b08ffc35971a584aedcc1cb8322b9d5fd9c9' | ||
|
||
// this DEK has been registered to the above account on alfajores | ||
const dekPrivateKey = '0xc2bbdabb440141efed205497a41d5fb6114e0435fd541e368dc628a8e086bfee' | ||
// const dekPublicKey = '0xc2bbdabb440141efed205497a41d5fb6114e0435fd541e368dc628a8e086bfee' | ||
|
||
const authSigner: AuthSigner = { | ||
authenticationMethod: AuthenticationMethod.ENCRYPTION_KEY, | ||
rawKey: dekPrivateKey, | ||
} | ||
const oldServiceContext = OdisUtils.Query.getServiceContext('alfajores') | ||
const currentServiceContext = getServiceContext('alfajores') | ||
|
||
const expectedObfuscatedIdentifier = | ||
'0xf82c6272fd57d3e5d4e291be16b3ebac5c616084a5e6f3730c73f62efd39c6ae' | ||
const expectedPepper = 'Pi4Z1NQnfsdvJ' | ||
|
||
describe('backwards compatibility of phone number identifiers', () => { | ||
beforeAll(() => { | ||
fetchMock.reset() | ||
// disables the mock, lets all calls fall through to the actual network | ||
fetchMock.spy() | ||
}) | ||
|
||
it('should match when using EncryptionSigner', async () => { | ||
const oldRes = await OdisUtils.PhoneNumberIdentifier.getPhoneNumberIdentifier( | ||
mockE164Number, | ||
mockAccount, | ||
authSigner, | ||
oldServiceContext | ||
) | ||
|
||
const currRes = await getObfuscatedIdentifier( | ||
mockE164Number, | ||
IdentifierPrefix.PHONE_NUMBER, | ||
mockAccount, | ||
authSigner, | ||
currentServiceContext | ||
) | ||
|
||
expect(oldRes.e164Number).toEqual(currRes.plaintextIdentifier) | ||
expect(oldRes.phoneHash).toEqual(expectedObfuscatedIdentifier) | ||
expect(currRes.obfuscatedIdentifier).toEqual(expectedObfuscatedIdentifier) | ||
expect(oldRes.pepper).toEqual(expectedPepper) | ||
expect(currRes.pepper).toEqual(expectedPepper) | ||
}, 20000) | ||
|
||
it('blinded identifier should match', async () => { | ||
const blsBlindingClient = new WasmBlsBlindingClient('') | ||
const seed = Buffer.from( | ||
'44714c0a2b2bacec757a67822a4fbbdfe043cca8c6ae936545ef992f246df1a9', | ||
'hex' | ||
) | ||
const oldRes = await OdisUtils.PhoneNumberIdentifier.getBlindedPhoneNumber( | ||
mockE164Number, | ||
blsBlindingClient, | ||
seed | ||
) | ||
const currentRes = await getBlindedIdentifier( | ||
mockE164Number, | ||
IdentifierPrefix.PHONE_NUMBER, | ||
blsBlindingClient, | ||
seed | ||
) | ||
|
||
const expectedBlindedIdentifier = | ||
'fuN6SmbxkYBqVbKZu4SizdyDjavNLK/XguIlwsWUhsWA0hQDoZtsZjQCbXqTnUiA' | ||
|
||
expect(oldRes).toEqual(expectedBlindedIdentifier) | ||
expect(currentRes).toEqual(expectedBlindedIdentifier) | ||
}) | ||
|
||
it('obfuscated identifier should match', async () => { | ||
const sha3 = (v: string) => soliditySha3({ type: 'string', value: v }) | ||
const oldRes = getPhoneHash(sha3, mockE164Number, expectedPepper) | ||
|
||
const currRes = getIdentifierHash(mockE164Number, IdentifierPrefix.PHONE_NUMBER, expectedPepper) | ||
|
||
expect(oldRes).toEqual(expectedObfuscatedIdentifier) | ||
expect(currRes).toEqual(expectedObfuscatedIdentifier) | ||
}) | ||
|
||
it('should not match when different prefix used', async () => { | ||
const oldRes = await OdisUtils.PhoneNumberIdentifier.getPhoneNumberIdentifier( | ||
mockE164Number, | ||
mockAccount, | ||
authSigner, | ||
oldServiceContext | ||
) | ||
|
||
const currRes = await getObfuscatedIdentifier( | ||
mockE164Number, | ||
'badPrefix', | ||
mockAccount, | ||
authSigner, | ||
currentServiceContext | ||
) | ||
|
||
expect(oldRes.e164Number).toEqual(currRes.plaintextIdentifier) | ||
expect(oldRes.phoneHash).not.toEqual(currRes.obfuscatedIdentifier) | ||
expect(oldRes.pepper).not.toEqual(currRes.pepper) | ||
}) | ||
}) |
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,156 @@ | ||
import { CombinerEndpoint } from '@celo/phone-number-privacy-common' | ||
import { WasmBlsBlindingClient } from './bls-blinding-client' | ||
import { | ||
getBlindedIdentifier, | ||
getBlindedIdentifierSignature, | ||
getObfuscatedIdentifier, | ||
getObfuscatedIdentifierFromSignature, | ||
getPepperFromThresholdSignature, | ||
IdentifierPrefix, | ||
} from './identifier' | ||
import { AuthenticationMethod, EncryptionKeySigner, ErrorMessages, ServiceContext } from './query' | ||
|
||
jest.mock('./bls-blinding-client', () => { | ||
// tslint:disable-next-line:no-shadowed-variable | ||
class WasmBlsBlindingClient { | ||
blindMessage = (m: string) => m | ||
unblindAndVerifyMessage = (m: string) => m | ||
} | ||
return { | ||
WasmBlsBlindingClient, | ||
} | ||
}) | ||
|
||
const mockOffchainIdentifier = 'twitterHandle' | ||
const mockAccount = '0x0000000000000000000000000000000000007E57' | ||
const expectedIdentifierHash = '0x8d1f580d4e49568883df9092285c0f8336e50d592b944607a613aff804e0b48f' | ||
const expectedPepper = 'nHIvMC9B4j2+H' | ||
|
||
const serviceContext: ServiceContext = { | ||
odisUrl: 'https://mockodis.com', | ||
odisPubKey: | ||
'7FsWGsFnmVvRfMDpzz95Np76wf/1sPaK0Og9yiB+P8QbjiC8FV67NBans9hzZEkBaQMhiapzgMR6CkZIZPvgwQboAxl65JWRZecGe5V3XO4sdKeNemdAZ2TzQuWkuZoA', | ||
} | ||
const endpoint = serviceContext.odisUrl + CombinerEndpoint.PNP_SIGN | ||
const rawKey = '41e8e8593108eeedcbded883b8af34d2f028710355c57f4c10a056b72486aa04' | ||
|
||
const authSigner: EncryptionKeySigner = { | ||
authenticationMethod: AuthenticationMethod.ENCRYPTION_KEY, | ||
rawKey, | ||
} | ||
|
||
describe(getObfuscatedIdentifier, () => { | ||
afterEach(() => { | ||
fetchMock.reset() | ||
}) | ||
|
||
describe('Retrieves a pepper correctly', () => { | ||
it('Using EncryptionKeySigner', async () => { | ||
fetchMock.mock(endpoint, { | ||
success: true, | ||
signature: '0Uj+qoAu7ASMVvm6hvcUGx2eO/cmNdyEgGn0mSoZH8/dujrC1++SZ1N6IP6v2I8A', | ||
performedQueryCount: 5, | ||
totalQuota: 10, | ||
version: '', | ||
}) | ||
|
||
const blsBlindingClient = new WasmBlsBlindingClient(serviceContext.odisPubKey) | ||
const base64BlindedMessage = await getBlindedIdentifier( | ||
mockOffchainIdentifier, | ||
IdentifierPrefix.TWITTER, | ||
blsBlindingClient | ||
) | ||
const base64BlindSig = await getBlindedIdentifierSignature( | ||
mockAccount, | ||
authSigner, | ||
serviceContext, | ||
base64BlindedMessage | ||
) | ||
const base64UnblindedSig = await blsBlindingClient.unblindAndVerifyMessage(base64BlindSig) | ||
|
||
await expect( | ||
getObfuscatedIdentifier( | ||
mockOffchainIdentifier, | ||
IdentifierPrefix.TWITTER, | ||
mockAccount, | ||
authSigner, | ||
serviceContext | ||
) | ||
).resolves.toMatchObject({ | ||
plaintextIdentifier: mockOffchainIdentifier, | ||
pepper: expectedPepper, | ||
obfuscatedIdentifier: expectedIdentifierHash, | ||
unblindedSignature: base64UnblindedSig, | ||
}) | ||
}) | ||
|
||
it('Preblinding the off-chain identifier', async () => { | ||
fetchMock.mock(endpoint, { | ||
success: true, | ||
signature: '0Uj+qoAu7ASMVvm6hvcUGx2eO/cmNdyEgGn0mSoZH8/dujrC1++SZ1N6IP6v2I8A', | ||
performedQueryCount: 5, | ||
totalQuota: 10, | ||
version: '', | ||
}) | ||
|
||
const blsBlindingClient = new WasmBlsBlindingClient(serviceContext.odisPubKey) | ||
const base64BlindedMessage = await getBlindedIdentifier( | ||
mockOffchainIdentifier, | ||
IdentifierPrefix.TWITTER, | ||
blsBlindingClient | ||
) | ||
|
||
const base64BlindSig = await getBlindedIdentifierSignature( | ||
mockAccount, | ||
authSigner, | ||
serviceContext, | ||
base64BlindedMessage | ||
) | ||
|
||
const obfuscatedIdentifierDetails = await getObfuscatedIdentifierFromSignature( | ||
mockOffchainIdentifier, | ||
IdentifierPrefix.TWITTER, | ||
base64BlindSig, | ||
blsBlindingClient | ||
) | ||
|
||
expect(obfuscatedIdentifierDetails.obfuscatedIdentifier).toEqual(expectedIdentifierHash) | ||
expect(obfuscatedIdentifierDetails.pepper).toEqual(expectedPepper) | ||
}) | ||
}) | ||
|
||
it('Throws quota error', async () => { | ||
fetchMock.mock(endpoint, 403) | ||
|
||
await expect( | ||
getObfuscatedIdentifier( | ||
mockOffchainIdentifier, | ||
IdentifierPrefix.PHONE_NUMBER, | ||
mockAccount, | ||
authSigner, | ||
serviceContext | ||
) | ||
).rejects.toThrow(ErrorMessages.ODIS_QUOTA_ERROR) | ||
}) | ||
|
||
it('Throws auth error', async () => { | ||
fetchMock.mock(endpoint, 401) | ||
await expect( | ||
getObfuscatedIdentifier( | ||
mockOffchainIdentifier, | ||
IdentifierPrefix.PHONE_NUMBER, | ||
mockAccount, | ||
authSigner, | ||
serviceContext | ||
) | ||
).rejects.toThrow(ErrorMessages.ODIS_AUTH_ERROR) | ||
}) | ||
}) | ||
|
||
describe(getPepperFromThresholdSignature, () => { | ||
it('Hashes sigs correctly', () => { | ||
const base64Sig = 'vJeFZJ3MY5KlpI9+kIIozKkZSR4cMymLPh2GHZUatWIiiLILyOcTiw2uqK/LBReA' | ||
const signature = Buffer.from(base64Sig, 'base64') | ||
expect(getPepperFromThresholdSignature(signature)).toBe('piWqRHHYWtfg9') | ||
}) | ||
}) |
Oops, something went wrong.