Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add odis-identifiers package (moved from celo/base) #104

Merged
merged 7 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/odd-foxes-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@celo/odis-identifiers': major
---

Initial Release. Move functions Enum from @celo/base
5 changes: 5 additions & 0 deletions .changeset/tasty-gifts-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@celo/odis-identifiers': minor
---

Add Github Prefix
4 changes: 4 additions & 0 deletions .github/workflows/social-connect.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,16 @@ jobs:
uses: ./.github/actions/sync-workspace
with:
package-json-checksum: ${{ needs.install-dependencies.outputs.package-json-checksum }}
- name: Run Odis Identifier Tests
run: |
yarn --cwd=packages/odis-identifiers test
- name: Run Encrypted Backup tests
run: |
yarn --cwd=packages/sdk/encrypted-backup test
- name: Run Identity Tests
run: |
yarn --cwd=packages/sdk/identity test

- name: Upload Jest Test Results
uses: actions/upload-artifact@v3
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,4 @@ scripts/failedSDKs.json

packages/protocol/types/typechain-mento/*.d.ts
tmp
packages/odis-identifiers/lib
8 changes: 8 additions & 0 deletions packages/odis-identifiers/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/src
*.test.*
# exclude ts files and sourcemaps
*.map
*.ts

# include the .d.ts files
!lib/**/*.d.ts
6 changes: 6 additions & 0 deletions packages/odis-identifiers/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
preset: 'ts-jest',
rootDir: './src/',
testMatch: ['<rootDir>/**/?(*.)+(spec|test).ts?(x)'],
verbose: true,
}
20 changes: 20 additions & 0 deletions packages/odis-identifiers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@celo/odis-identifiers",
"author": "cLabs",
"license": "Apache-2.0",
"private": false,
"version": "0.0.1",
"description": "ODIS Identifier Prefixes and functions to hash identifiers",
"repository": "https://github.com/celo-org/social-connect",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"scripts": {
"build": "tsc -b .",
"clean": "tsc -b . --clean",
"test": "jest --runInBand",
"lint": "eslint ."
},
"devDependencies": {
"web3-utils": "1.10.0"
}
}
34 changes: 34 additions & 0 deletions packages/odis-identifiers/src/identifier.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { soliditySha3 } from 'web3-utils'
import { getIdentifierHash, IdentifierPrefix } from './index'
const sha3 = (v: string) => soliditySha3({ type: 'string', value: v })

const TEST_SALT = 'abcdefg'
const TEST_PLAINTEXT_IDENTIFIER = '+testIdentifier@'

const EXPECTED_HASH_FOR_PREFIX: Record<IdentifierPrefix, string> = {
[IdentifierPrefix.NULL]: '0x9ba535838da6c3b9e5052e63261deb872451a45d24cbbc2e0153a02b151702e3',
[IdentifierPrefix.PHONE_NUMBER]:
'0x1c404f57b436d75c6c63547c795d1d475c87dcd7bce6413fb016483e815335ee',
[IdentifierPrefix.EMAIL]: '0xaa47e9630a60f2e6667b310164b82d973124fc462e0361750fb36cf9f0e6ee16',
[IdentifierPrefix.TWITTER]: '0x9bb3eedf112f5ff18ec50467e2422fa1c2df01550fd650970e7aec3d52bc5ea9',
[IdentifierPrefix.FACEBOOK]: '0x883c8d998c5e75e7014fdcd1f75976032023fbfe89707d030f22367f501e08e8',
[IdentifierPrefix.INSTAGRAM]:
'0x3b212606f77d62fa85f636d76ab499306bed09f7f23e39db6aba348000c54d48',
[IdentifierPrefix.DISCORD]: '0xce7834e8e3c84180fab3a97b099dd131a78f9c91c3ae9753412423dc7ffdbdaa',
[IdentifierPrefix.TELEGRAM]: '0x65ecb839a118e293672aa7556dcff3f5d82dd142835e9d6f45b9539f252b3c6c',
[IdentifierPrefix.SIGNAL]: '0x34702bc6c5253a4d9521da1f45cec9eac3969c9cae7380aac422e2b872019182',
[IdentifierPrefix.GITHUB]: '0xd0a0e7f10b99db21f6a066398baa0bb50c4e8c1768d98104abc56ed000fe81c3',
}

describe('Identifier hashing', () => {
describe('Produces correct hash', () => {
Object.values(IdentifierPrefix).forEach((prefix: IdentifierPrefix) => {
it(`with IdentifierPrefix: ${prefix}`, () => {
const expectedHash = EXPECTED_HASH_FOR_PREFIX[prefix]
expect(getIdentifierHash(sha3, TEST_PLAINTEXT_IDENTIFIER, prefix, TEST_SALT)).toBe(
expectedHash
)
})
})
})
})
85 changes: 85 additions & 0 deletions packages/odis-identifiers/src/identifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// These functions were moved from the identity SDK because the protocol package
// and @celo/phone-utils both need these core identifier generation functions as well.
// The protocol package cannot depend on the identity SDK as is since this creates
// a non-trivial dependency cycle (currently, if A->B means "A depends on B",
// identity -> phone-number-privacy-common -> contractkit -> protocol).

export const PEPPER_SEPARATOR = '__'

// Docstring is duplicated in @celo/identity; make sure to update in both places.
/**
* Standardized prefixes for ODIS identifiers.
*
* @remarks These prefixes prevent collisions between off-chain identifiers.
* i.e. if a user's instagram and twitter handles are the same,
* these prefixes prevent the ODIS identifers from being the same.
*
* If you would like to use a prefix that isn't included, please put up a PR
* adding it to @celo/base (in celo-monorepo/packages/sdk/base/src/identifier.ts)
* to ensure interoperability with other projects. When adding new prefixes,
* please use either the full platform name in all lowercase (e.g. 'facebook')
* or DID methods https://w3c.github.io/did-spec-registries/#did-methods.
* Make sure to add the expected value for the unit test case in
* `celo-monorepo/packages/sdk/base/src/identifier.test.ts`,
* otherwise the test will fail.
*
* The NULL prefix is included to allow projects to use the sdk without selecting
* a predefined prefix or adding their own. Production use of the NULL prefix is
* discouraged since identifiers will not be interoperable with other projects.
* Please think carefully before using the NULL prefix.
*/
export enum IdentifierPrefix {
NULL = '',
PHONE_NUMBER = 'tel',
EMAIL = 'mailto',
TWITTER = 'twit',
FACEBOOK = 'facebook',
INSTAGRAM = 'instagram',
DISCORD = 'discord',
TELEGRAM = 'telegram',
SIGNAL = 'signal',
GITHUB = 'github',
}

// Docstring is duplicated in @celo/identity; make sure to update in both places.
/**
* Concatenates the identifierPrefix and plaintextIdentifier with the separator '://'
*
* @param plaintextIdentifier Off-chain identifier, ex: phone number, twitter handle, email, etc.
* @param identifierPrefix Standardized prefix used to prevent collisions between identifiers
*/
export const getPrefixedIdentifier = (
plaintextIdentifier: string,
identifierPrefix: IdentifierPrefix
): string => identifierPrefix + '://' + plaintextIdentifier

/**
* Helper function for getIdentifierHash in @celo/identity, so that this can
* be used in protocol tests without dependency issues.
*
* @remarks
* Concatenates the plaintext prefixed identifier with the pepper derived by hashing the unblinded
* signature returned by ODIS.
*
* @param sha3 Hash function (i.e. soliditySha3) to use to generate the identifier
* @param plaintextIdentifier Off-chain identifier, ex: phone number, twitter handle, email, etc.
* @param identifierPrefix Standardized prefix used to prevent collisions between identifiers
* @param pepper Hash of the unblinded signature returned by ODIS
*/
export const getIdentifierHash = (
sha3: (a: string) => string | null,
plaintextIdentifier: string,
identifierPrefix: IdentifierPrefix,
pepper: string
): string => {
// hashing the identifier before appending the pepper to avoid domain collisions where the
// identifier may contain underscores
// not doing this for phone numbers to maintain backwards compatibility
const value =
identifierPrefix === IdentifierPrefix.PHONE_NUMBER
? getPrefixedIdentifier(plaintextIdentifier, identifierPrefix) + PEPPER_SEPARATOR + pepper
: (sha3(getPrefixedIdentifier(plaintextIdentifier, identifierPrefix)) as string) +
PEPPER_SEPARATOR +
pepper
return sha3(value) as string
}
1 change: 1 addition & 0 deletions packages/odis-identifiers/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './identifier'
11 changes: 11 additions & 0 deletions packages/odis-identifiers/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "@tsconfig/recommended",
"compilerOptions": {
"declaration": true,
"removeComments":true,
"rootDir": "src",
"outDir": "lib"
},
"include": ["src", "index.d.ts"],
"compileOnSave": true
}
1 change: 1 addition & 0 deletions packages/sdk/identity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@celo/base": "^5.0.4",
"@celo/utils": "^5.0.4",
"@celo/contractkit": "^5.0.4",
"@celo/odis-identifiers": "^0.0.1",
"@celo/phone-number-privacy-common": "^3.0.3",
"@types/debug": "^4.1.5",
"bignumber.js": "^9.0.0",
Expand Down
10 changes: 5 additions & 5 deletions packages/sdk/identity/src/odis/identifier.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { isE164Number } from '@celo/base/lib/phoneNumbers'
import {
IdentifierPrefix,
getIdentifierHash as baseGetIdentifierHash,
getPrefixedIdentifier,
IdentifierPrefix,
isE164Number,
} from '@celo/base'
} from '@celo/odis-identifiers'
import {
CombinerEndpointPNP,
KEY_VERSION_HEADER,
Expand All @@ -15,12 +15,12 @@ import { createHash } from 'crypto'
import debugFactory from 'debug'
import { BlsBlindingClient, WasmBlsBlindingClient } from './bls-blinding-client'
import {
AuthenticationMethod,
AuthSigner,
AuthenticationMethod,
EncryptionKeySigner,
ServiceContext,
getOdisPnpRequestAuth,
queryOdis,
ServiceContext,
} from './query'

const debug = debugFactory('kit:odis:identifier')
Expand Down
Loading