Skip to content

Commit

Permalink
feat: siwe
Browse files Browse the repository at this point in the history
  • Loading branch information
hai-ko committed Nov 24, 2023
1 parent fc35eca commit 6dbcffc
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export async function getBillboardProfile(
const wallet = new ethers.Wallet(billboard.privateKey);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
'0xca8f04fdc80d659997f69b02',
wallet.address,
);
const storageKeySig = await wallet.signMessage(
storageKeyCreationMessage,
Expand Down
1 change: 1 addition & 0 deletions packages/billboard-client/test/helper/mockUserProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const mockUserProfile = async (
}> => {
const storageKeyCreationMessage = getStorageKeyCreationMessage(
'0xca8f04fdc80d659997f69b02',
wallet.address,
);

const storageKeySig = await wallet.signMessage(storageKeyCreationMessage);
Expand Down
9 changes: 0 additions & 9 deletions packages/lib/crypto/src/KeyCreation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,6 @@ import {
getStorageKeyCreationMessage,
} from './KeyCreation';

test('should get a correct storage key creation message', async () => {
const message = await getStorageKeyCreationMessage('99');
expect(message).toEqual(
'Connect the dm3 app with your wallet.' +
' Keys for secure communication are derived from the signature.' +
' No paid transaction will be executed.\nNonce: 99',
);
});

test('should get a correct storage key', async () => {
const sig =
'0xb9b0a77f501c6db70c5e8f7d1e6be1642b8b7e897d681c69921569cb84b0a' +
Expand Down
20 changes: 16 additions & 4 deletions packages/lib/crypto/src/KeyCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,23 @@ export async function createSigningKeyPair(seed?: string): Promise<KeyPair> {
};
}

export function getStorageKeyCreationMessage(nonce: string) {
export function getStorageKeyCreationMessage(nonce: string, address: string) {
// TODO: during linked profile implementation these values should be fetched from env
const statement =
`Connect the DM3 MESSENGER with your wallet. Sign in with a signature. ` +
`Keys for secure communication are derived from this signature.\n\n` +
`(There is no paid transaction initiated. The signature is used off-chain only.)`;
const domain = 'dm3.chat';
const uri = 'https://dm3.chat';
const version = '1';

return (
`Connect the dm3 app with your wallet.` +
` Keys for secure communication are derived from the signature.` +
` No paid transaction will be executed.\nNonce: ${nonce}`
`${domain} wants you to sign in with your Ethereum account:\n` +
`${ethers.utils.getAddress(address)}\n\n` +
`${statement}\n\n` +
`URI: ${uri}\n` +
`Version: ${version}\n` +
`Nonce: ${nonce}`
);
}

Expand Down
2 changes: 2 additions & 0 deletions packages/lib/profile/src/Profile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const getProfileData = async (): Promise<{

const createUserProfileMessage = getProfileCreationMessage(
stringify(profile),
wallet.address,
);
const signature = await wallet.signMessage(createUserProfileMessage);

Expand Down Expand Up @@ -140,6 +141,7 @@ describe('Account', () => {
const wallet = ethers.Wallet.createRandom();
const createUserProfileMessage = getProfileCreationMessage(
stringify(profile),
wallet.address,
);
const signature = await wallet.signMessage(
createUserProfileMessage,
Expand Down
29 changes: 23 additions & 6 deletions packages/lib/profile/src/Profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,22 @@ export const PROFILE_RECORD_NAME = 'network.dm3.profile';
* signs a profile with an ethereum account key
* @param stringifiedProfile stringified dm3 user profile object
*/
export function getProfileCreationMessage(stringifiedProfile: string) {
export function getProfileCreationMessage(
stringifiedProfile: string,
address: string,
) {
const domain = 'dm3.chat';
const uri = 'https://dm3.chat';
const version = '1';

return (
`Please sign this message to link your dm3 profile with your Wallet. ` +
`(This signature will not trigger any transaction or cost gas fees.) ` +
`Your dm3 profile:\n\n${stringifiedProfile}`
`${domain} wants you register your dm3 profile with your Ethereum account:\n` +
`${ethers.utils.getAddress(address)}\n\n` +
`Register your dm3 profile. This is required only once!\n` +
`(There is no paid transaction initiated. The signature is used off-chain only.)\n\n` +
`URI: ${uri}\n` +
`Version: ${version}\n` +
`dm3 Profile: ${stringifiedProfile}`
);
}

Expand Down Expand Up @@ -116,6 +127,7 @@ export function checkUserProfileWithAddress(
): boolean {
const createUserProfileMessage = getProfileCreationMessage(
stringify(profile),
accountAddress,
);

return (
Expand Down Expand Up @@ -192,12 +204,15 @@ export function isSameEnsName(

async function createKeyPairsFromSig(
sign: (msg: string) => Promise<string>,

address: string,
nonce: string,
storageKey?: string,
): Promise<ProfileKeys> {
if (!storageKey) {
const storageKeyCreationMessage = getStorageKeyCreationMessage(nonce);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
nonce,
address,
);
const signature = await sign(storageKeyCreationMessage);

const newStorageKey = await createStorageKey(signature);
Expand Down Expand Up @@ -235,6 +250,7 @@ export async function createProfile(

const keys = await createKeyPairsFromSig(
(msg: string) => signer(msg, accountAddress),
accountAddress,
nonce,
storageKey,
);
Expand All @@ -247,6 +263,7 @@ export async function createProfile(

const profileCreationMessage = getProfileCreationMessage(
stringify(profile),
accountAddress,
);
const profileSig = await signer(profileCreationMessage, accountAddress);
return {
Expand Down
12 changes: 6 additions & 6 deletions packages/lib/profile/src/profileKeys/createProfileKeys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ test(`Should create keys`, async () => {
'0xac58f2f021d6f148fd621b355edbd0ebadcf9682019015ef1219cf9c0c2ddc8b',
);

const nonceMsg = getStorageKeyCreationMessage(nonce);
const nonceMsg = getStorageKeyCreationMessage(nonce, wallet.address);
const signedMessage = await wallet.signMessage(nonceMsg);

const keys = await createProfileKeys(
Expand All @@ -20,15 +20,15 @@ test(`Should create keys`, async () => {

expect(keys).toEqual({
encryptionKeyPair: {
privateKey: 'g79U2C3cVkSHwrdDAF1klEdhdAtZXdspTBOoAohYPlQ=',
publicKey: 'PKz2kFF0zqaWD4/vIMiADZmGKcf4tKo5/Wq9KDPlBlo=',
privateKey: '0wMyWrdDXCfuwRq4nm6IHqZ7hMbPOb5DsTt1C85w+zE=',
publicKey: 'JBvXxZY4BOnKK4J2s42ZpAJaFd/nmB5Sq7EB+jfA6H8=',
},
signingKeyPair: {
publicKey: 'Z35n4cFXhCdDHmLwVPYHwHwiJlYr+Ga0dbPWj8/mxAE=',
privateKey:
'mxwp2Ygys2U3ary7cL0dDbh6TwYl3nEeDVzEaFS01NZnfmfhwVeEJ0MeYvBU9gfAfCImViv4ZrR1s9aPz+bEAQ==',
'ti4w8V+E6x4Z63XIMA9ZM0lXKhMjTaxP/qjARC8c4CxRQS5qo2AEYU+ZeFyB0bksaPBX1K5/QA/dregbbmFgQQ==',
publicKey: 'UUEuaqNgBGFPmXhcgdG5LGjwV9Suf0AP3a3oG25hYEE=',
},
storageEncryptionKey: 'mxwp2Ygys2U3ary7cL0dDbh6TwYl3nEeDVzEaFS01NY=',
storageEncryptionKey: 'ti4w8V+E6x4Z63XIMA9ZM0lXKhMjTaxP/qjARC8c4Cw=',
storageEncryptionNonce: '0',
});
});
41 changes: 22 additions & 19 deletions packages/messenger-widget/src/components/SignIn/bl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ export const checkState = async (
const browserDataFile =
state.connection.account && state.uiState.browserStorageBackup
? await localforage.getItem(
getBrowserStorageKey(state.connection.account.ensName),
)
getBrowserStorageKey(state.connection.account.ensName),
)
: null;

const isCollectingSignInData =
Expand Down Expand Up @@ -171,7 +171,10 @@ export async function createKeyPairsFromSignature(
throw Error('No eth address');
}

const storageKeyCreationMessage = getStorageKeyCreationMessage(nonce);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
nonce,
ethAddress,
);

const signature = await personalSign(
provider,
Expand Down Expand Up @@ -347,7 +350,7 @@ export async function signProfile(
): Promise<string> {
try {
const profileCreationMessage =
getProfileCreationMessage(stringifiedProfile);
getProfileCreationMessage(stringifiedProfile, address);
return await personalSign(provider, address, profileCreationMessage);
} catch (error: any) {
const err = error?.message.split(':');
Expand Down Expand Up @@ -481,12 +484,12 @@ export async function getDatabase(
}> {
return profileExists
? getExistingDatebase(
storageLocation,
storageToken,
state,
dispatch,
setSignInBtnContent,
)
storageLocation,
storageToken,
state,
dispatch,
setSignInBtnContent,
)
: createNewDatabase(state, setSignInBtnContent);
}

Expand Down Expand Up @@ -814,16 +817,16 @@ export async function getWeb3Provider(provider: unknown): Promise<{
}> {
return provider
? {
provider: new ethers.providers.Web3Provider(
provider as
| ethers.providers.ExternalProvider
| ethers.providers.JsonRpcFetchFunc,
),
connectionState: ConnectionState.AccountConnectReady,
}
provider: new ethers.providers.Web3Provider(
provider as
| ethers.providers.ExternalProvider
| ethers.providers.JsonRpcFetchFunc,
),
connectionState: ConnectionState.AccountConnectReady,
}
: {
connectionState: ConnectionState.ConnectionRejected,
};
connectionState: ConnectionState.ConnectionRejected,
};
}

function handleNewProvider(
Expand Down
6 changes: 4 additions & 2 deletions packages/react/src/session/SignIn/signProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ export async function signProfile(
stringifiedProfile: string,
): Promise<string> {
try {
const profileCreationMessage =
getProfileCreationMessage(stringifiedProfile);
const profileCreationMessage = getProfileCreationMessage(
stringifiedProfile,
address,
);
return await personalSign(provider, address, profileCreationMessage);
} catch (e) {
throw Error("Can't signIn profile");
Expand Down
5 changes: 4 additions & 1 deletion packages/react/src/session/SignIn/signProfileKeyPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export async function createKeyPairsFromSig(
throw Error('No eth address');
}

const storageKeyCreationMessage = getStorageKeyCreationMessage(nonce);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
nonce,
ethAddress,
);

const signature = await personalSign(
provider,
Expand Down

0 comments on commit 6dbcffc

Please sign in to comment.