@graphprotocol/hypergraph 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/dist/connect/auth-storage.d.ts.map +1 -0
- package/dist/connect/create-app-identity.d.ts.map +1 -0
- package/dist/connect/create-auth-url.d.ts.map +1 -0
- package/dist/connect/create-auth-url.js +35 -0
- package/dist/connect/create-auth-url.js.map +1 -0
- package/dist/connect/create-callback-params.d.ts.map +1 -0
- package/dist/connect/create-callback-params.js +17 -0
- package/dist/connect/create-callback-params.js.map +1 -0
- package/dist/connect/create-identity-keys.d.ts.map +1 -0
- package/dist/connect/identity-encryption.d.ts.map +1 -0
- package/dist/connect/index.d.ts.map +1 -0
- package/dist/connect/login.d.ts.map +1 -0
- package/dist/connect/parse-callback-params.d.ts.map +1 -0
- package/dist/connect/parse-callback-params.js +63 -0
- package/dist/connect/parse-callback-params.js.map +1 -0
- package/dist/connect/prove-ownership.d.ts.map +1 -0
- package/dist/connect/types.d.ts +57 -0
- package/dist/connect/types.d.ts.map +1 -0
- package/dist/connect/types.js +24 -0
- package/dist/connect/types.js.map +1 -0
- package/dist/entity/create.d.ts.map +1 -0
- package/dist/entity/decodedEntitiesCache.d.ts.map +1 -0
- package/dist/entity/delete.d.ts.map +1 -0
- package/dist/entity/entity.d.ts.map +1 -0
- package/dist/entity/entityRelationParentsMap.d.ts.map +1 -0
- package/dist/entity/findMany.d.ts.map +1 -0
- package/dist/entity/findMany.js +436 -0
- package/dist/entity/findMany.js.map +1 -0
- package/dist/entity/findOne.d.ts.map +1 -0
- package/dist/entity/getEntityRelations.d.ts.map +1 -0
- package/dist/entity/index.d.ts.map +1 -0
- package/dist/entity/relationParentsMap.d.ts.map +1 -0
- package/dist/entity/removeRelation.d.ts.map +1 -0
- package/dist/entity/types.d.ts +79 -0
- package/dist/entity/types.d.ts.map +1 -0
- package/dist/entity/types.js +2 -0
- package/dist/entity/types.js.map +1 -0
- package/dist/entity/update.d.ts.map +1 -0
- package/dist/identity/auth-storage.d.ts.map +1 -0
- package/dist/identity/get-verified-identity.d.ts.map +1 -0
- package/dist/identity/identity-encryption.d.ts.map +1 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/logout.d.ts.map +1 -0
- package/dist/identity/prove-ownership.d.ts.map +1 -0
- package/dist/inboxes/create-inbox.d.ts.map +1 -0
- package/dist/inboxes/get-list-inboxes.d.ts.map +1 -0
- package/dist/inboxes/index.d.ts.map +1 -0
- package/dist/inboxes/merge-messages.d.ts.map +1 -0
- package/dist/inboxes/message-encryption.d.ts.map +1 -0
- package/dist/inboxes/message-validation.d.ts.map +1 -0
- package/dist/inboxes/prepare-message.d.ts +31 -0
- package/dist/inboxes/prepare-message.d.ts.map +1 -0
- package/dist/inboxes/recover-inbox-creator.d.ts.map +1 -0
- package/dist/inboxes/recover-inbox-message-signer.d.ts.map +1 -0
- package/dist/inboxes/send-message.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/signed-update-message.d.ts.map +1 -0
- package/dist/messages/types.d.ts.map +1 -0
- package/dist/space-events/accept-invitation.d.ts.map +1 -0
- package/dist/space-events/apply-event.d.ts.map +1 -0
- package/dist/space-events/create-inbox.d.ts.map +1 -0
- package/dist/space-events/create-invitation.d.ts.map +1 -0
- package/dist/space-events/create-space.d.ts.map +1 -0
- package/dist/space-events/delete-space.d.ts.map +1 -0
- package/dist/space-events/hash-event.d.ts.map +1 -0
- package/dist/space-events/index.d.ts.map +1 -0
- package/dist/space-info/decrypt-space-info.d.ts.map +1 -0
- package/dist/space-info/encrypt-and-sign-space-info.d.ts.map +1 -0
- package/dist/space-info/index.d.ts.map +1 -0
- package/dist/store-connect.d.ts.map +1 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/type/type.d.ts.map +1 -0
- package/dist/utils/automergeId.d.ts +9 -0
- package/dist/utils/automergeId.d.ts.map +1 -0
- package/dist/utils/automergeId.js +17 -0
- package/dist/utils/automergeId.js.map +1 -0
- package/dist/utils/generateId.d.ts +15 -0
- package/dist/utils/generateId.d.ts.map +1 -0
- package/dist/utils/generateId.js +18 -0
- package/dist/utils/generateId.js.map +1 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/package.json +35 -0
- package/src/connect/auth-storage.ts +67 -0
- package/src/connect/create-app-identity.ts +16 -0
- package/src/connect/create-auth-url.ts +42 -0
- package/src/connect/create-callback-params.ts +30 -0
- package/src/connect/create-identity-keys.ts +20 -0
- package/src/connect/identity-encryption.ts +232 -0
- package/src/connect/index.ts +10 -0
- package/src/connect/login.ts +114 -0
- package/src/connect/parse-auth-params.ts +37 -0
- package/src/connect/parse-callback-params.ts +67 -0
- package/src/connect/prove-ownership.ts +58 -0
- package/src/connect/types.ts +67 -0
- package/src/entity/create.ts +58 -0
- package/src/entity/decodedEntitiesCache.ts +38 -0
- package/src/entity/delete.ts +52 -0
- package/src/entity/entity.ts +26 -0
- package/src/entity/entityRelationParentsMap.ts +6 -0
- package/src/entity/findMany.ts +506 -0
- package/src/entity/findOne.ts +34 -0
- package/src/entity/getEntityRelations.ts +45 -0
- package/src/entity/hasValidTypesProperty.ts +8 -0
- package/src/entity/index.ts +8 -0
- package/src/entity/relationParentsMap.ts +6 -0
- package/src/entity/removeRelation.ts +21 -0
- package/src/entity/test.ts +0 -0
- package/src/entity/types.ts +100 -0
- package/src/entity/update.ts +58 -0
- package/src/entity/variant-schema.ts +677 -0
- package/src/identity/auth-storage.ts +57 -0
- package/src/identity/get-verified-identity.ts +53 -0
- package/src/identity/identity-encryption.ts +140 -0
- package/src/identity/index.ts +6 -0
- package/src/identity/logout.ts +8 -0
- package/src/identity/prove-ownership.ts +58 -0
- package/src/identity/types.ts +44 -0
- package/src/inboxes/create-inbox.ts +102 -0
- package/src/inboxes/get-list-inboxes.ts +52 -0
- package/src/inboxes/index.ts +10 -0
- package/src/inboxes/merge-messages.ts +28 -0
- package/src/inboxes/message-encryption.ts +35 -0
- package/src/inboxes/message-validation.ts +66 -0
- package/src/inboxes/prepare-message.ts +85 -0
- package/src/inboxes/recover-inbox-creator.ts +29 -0
- package/src/inboxes/recover-inbox-message-signer.ts +42 -0
- package/src/inboxes/send-message.ts +75 -0
- package/src/inboxes/types.ts +9 -0
- package/src/index.ts +13 -0
- package/src/key/create-key.ts +27 -0
- package/src/key/decrypt-key.ts +19 -0
- package/src/key/encrypt-key.ts +27 -0
- package/src/key/index.ts +4 -0
- package/src/key/key-box.ts +31 -0
- package/src/messages/decrypt-message.ts +13 -0
- package/src/messages/encrypt-message.ts +14 -0
- package/src/messages/index.ts +5 -0
- package/src/messages/serialize.ts +24 -0
- package/src/messages/signed-update-message.ts +84 -0
- package/src/messages/types.ts +506 -0
- package/src/space-events/accept-invitation.ts +36 -0
- package/src/space-events/apply-event.ts +150 -0
- package/src/space-events/create-inbox.ts +56 -0
- package/src/space-events/create-invitation.ts +41 -0
- package/src/space-events/create-space.ts +35 -0
- package/src/space-events/delete-space.ts +36 -0
- package/src/space-events/hash-event.ts +10 -0
- package/src/space-events/index.ts +8 -0
- package/src/space-events/types.ts +137 -0
- package/src/space-info/decrypt-space-info.ts +22 -0
- package/src/space-info/encrypt-and-sign-space-info.ts +50 -0
- package/src/space-info/index.ts +3 -0
- package/src/space-info/types.ts +7 -0
- package/src/store-connect.ts +504 -0
- package/src/store.ts +493 -0
- package/src/type/type.ts +25 -0
- package/src/types.ts +47 -0
- package/src/utils/assertExhaustive.ts +3 -0
- package/src/utils/automergeId.ts +18 -0
- package/src/utils/base58.ts +74 -0
- package/src/utils/generateId.ts +18 -0
- package/src/utils/hexBytesAddressUtils.ts +25 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/internal/base58Utils.ts +47 -0
- package/src/utils/internal/deep-merge.ts +38 -0
- package/src/utils/isRelationField.ts +9 -0
- package/src/utils/jsc.ts +94 -0
- package/src/utils/stringToUint8Array.ts +9 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
2
|
+
import type * as Messages from '../messages/index.js';
|
|
3
|
+
import type { SignatureWithRecovery } from '../types.js';
|
|
4
|
+
import { canonicalize, hexToBytes, stringToUint8Array } from '../utils/index.js';
|
|
5
|
+
import { encryptInboxMessage } from './message-encryption.js';
|
|
6
|
+
|
|
7
|
+
export async function prepareSpaceInboxMessage({
|
|
8
|
+
message,
|
|
9
|
+
spaceId,
|
|
10
|
+
inboxId,
|
|
11
|
+
encryptionPublicKey,
|
|
12
|
+
signaturePrivateKey,
|
|
13
|
+
authorAccountAddress,
|
|
14
|
+
}: Readonly<{
|
|
15
|
+
message: string;
|
|
16
|
+
spaceId: string;
|
|
17
|
+
inboxId: string;
|
|
18
|
+
encryptionPublicKey: string;
|
|
19
|
+
signaturePrivateKey: string | null;
|
|
20
|
+
authorAccountAddress: string | null;
|
|
21
|
+
}>) {
|
|
22
|
+
const { ciphertext } = encryptInboxMessage({ message, encryptionPublicKey });
|
|
23
|
+
let signature: SignatureWithRecovery | undefined;
|
|
24
|
+
if (signaturePrivateKey && authorAccountAddress) {
|
|
25
|
+
const messageToSign = stringToUint8Array(
|
|
26
|
+
canonicalize({
|
|
27
|
+
spaceId,
|
|
28
|
+
inboxId,
|
|
29
|
+
ciphertext,
|
|
30
|
+
authorAccountAddress,
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
const signatureInstance = secp256k1.sign(messageToSign, hexToBytes(signaturePrivateKey), { prehash: true });
|
|
34
|
+
signature = {
|
|
35
|
+
hex: signatureInstance.toCompactHex(),
|
|
36
|
+
recovery: signatureInstance.recovery,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const messageToSend: Messages.RequestCreateSpaceInboxMessage = {
|
|
40
|
+
ciphertext,
|
|
41
|
+
signature,
|
|
42
|
+
authorAccountAddress: authorAccountAddress ?? undefined,
|
|
43
|
+
};
|
|
44
|
+
return messageToSend;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function prepareAccountInboxMessage({
|
|
48
|
+
message,
|
|
49
|
+
accountAddress,
|
|
50
|
+
inboxId,
|
|
51
|
+
encryptionPublicKey,
|
|
52
|
+
signaturePrivateKey,
|
|
53
|
+
authorAccountAddress,
|
|
54
|
+
}: Readonly<{
|
|
55
|
+
message: string;
|
|
56
|
+
accountAddress: string;
|
|
57
|
+
inboxId: string;
|
|
58
|
+
encryptionPublicKey: string;
|
|
59
|
+
signaturePrivateKey: string | null;
|
|
60
|
+
authorAccountAddress: string | null;
|
|
61
|
+
}>) {
|
|
62
|
+
const { ciphertext } = encryptInboxMessage({ message, encryptionPublicKey });
|
|
63
|
+
let signature: SignatureWithRecovery | undefined;
|
|
64
|
+
if (signaturePrivateKey && authorAccountAddress) {
|
|
65
|
+
const messageToSign = stringToUint8Array(
|
|
66
|
+
canonicalize({
|
|
67
|
+
accountAddress,
|
|
68
|
+
inboxId,
|
|
69
|
+
ciphertext,
|
|
70
|
+
authorAccountAddress,
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
73
|
+
const signatureInstance = secp256k1.sign(messageToSign, hexToBytes(signaturePrivateKey), { prehash: true });
|
|
74
|
+
signature = {
|
|
75
|
+
hex: signatureInstance.toCompactHex(),
|
|
76
|
+
recovery: signatureInstance.recovery,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const messageToSend: Messages.RequestCreateAccountInboxMessage = {
|
|
80
|
+
ciphertext,
|
|
81
|
+
signature,
|
|
82
|
+
authorAccountAddress: authorAccountAddress ?? undefined,
|
|
83
|
+
};
|
|
84
|
+
return messageToSend;
|
|
85
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
+
import type { AccountInbox } from '../messages/index.js';
|
|
4
|
+
import type { CreateSpaceInboxEvent } from '../space-events/index.js';
|
|
5
|
+
import { canonicalize, stringToUint8Array } from '../utils/index.js';
|
|
6
|
+
|
|
7
|
+
export const recoverAccountInboxCreatorKey = (inbox: AccountInbox): string => {
|
|
8
|
+
const messageToVerify = stringToUint8Array(
|
|
9
|
+
canonicalize({
|
|
10
|
+
accountAddress: inbox.accountAddress,
|
|
11
|
+
inboxId: inbox.inboxId,
|
|
12
|
+
encryptionPublicKey: inbox.encryptionPublicKey,
|
|
13
|
+
}),
|
|
14
|
+
);
|
|
15
|
+
const signature = inbox.signature;
|
|
16
|
+
let signatureInstance = secp256k1.Signature.fromCompact(signature.hex);
|
|
17
|
+
signatureInstance = signatureInstance.addRecoveryBit(signature.recovery);
|
|
18
|
+
const authorPublicKey = `0x${signatureInstance.recoverPublicKey(sha256(messageToVerify)).toHex()}`;
|
|
19
|
+
return authorPublicKey;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const recoverSpaceInboxCreatorKey = (event: CreateSpaceInboxEvent): string => {
|
|
23
|
+
const messageToVerify = stringToUint8Array(canonicalize(event.transaction));
|
|
24
|
+
const signature = event.author.signature;
|
|
25
|
+
let signatureInstance = secp256k1.Signature.fromCompact(signature.hex);
|
|
26
|
+
signatureInstance = signatureInstance.addRecoveryBit(signature.recovery);
|
|
27
|
+
const authorPublicKey = `0x${signatureInstance.recoverPublicKey(sha256(messageToVerify)).toHex()}`;
|
|
28
|
+
return authorPublicKey;
|
|
29
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
+
import type * as Messages from '../messages/index.js';
|
|
4
|
+
import * as Utils from '../utils/index.js';
|
|
5
|
+
|
|
6
|
+
export const recoverSpaceInboxMessageSigner = (
|
|
7
|
+
message: Messages.RequestCreateSpaceInboxMessage,
|
|
8
|
+
spaceId: string,
|
|
9
|
+
inboxId: string,
|
|
10
|
+
) => {
|
|
11
|
+
if (!message.signature) {
|
|
12
|
+
throw new Error('Signature is required');
|
|
13
|
+
}
|
|
14
|
+
let signatureInstance = secp256k1.Signature.fromCompact(message.signature.hex);
|
|
15
|
+
signatureInstance = signatureInstance.addRecoveryBit(message.signature.recovery);
|
|
16
|
+
const signedMessage = {
|
|
17
|
+
spaceId,
|
|
18
|
+
inboxId,
|
|
19
|
+
ciphertext: message.ciphertext,
|
|
20
|
+
authorAccountAddress: message.authorAccountAddress,
|
|
21
|
+
};
|
|
22
|
+
return `0x${signatureInstance.recoverPublicKey(sha256(Utils.stringToUint8Array(Utils.canonicalize(signedMessage)))).toHex()}`;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const recoverAccountInboxMessageSigner = (
|
|
26
|
+
message: Messages.RequestCreateAccountInboxMessage,
|
|
27
|
+
accountAddress: string,
|
|
28
|
+
inboxId: string,
|
|
29
|
+
) => {
|
|
30
|
+
if (!message.signature) {
|
|
31
|
+
throw new Error('Signature is required');
|
|
32
|
+
}
|
|
33
|
+
let signatureInstance = secp256k1.Signature.fromCompact(message.signature.hex);
|
|
34
|
+
signatureInstance = signatureInstance.addRecoveryBit(message.signature.recovery);
|
|
35
|
+
const signedMessage = {
|
|
36
|
+
accountAddress,
|
|
37
|
+
inboxId,
|
|
38
|
+
ciphertext: message.ciphertext,
|
|
39
|
+
authorAccountAddress: message.authorAccountAddress,
|
|
40
|
+
};
|
|
41
|
+
return `0x${signatureInstance.recoverPublicKey(sha256(Utils.stringToUint8Array(Utils.canonicalize(signedMessage)))).toHex()}`;
|
|
42
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { prepareAccountInboxMessage, prepareSpaceInboxMessage } from './prepare-message.js';
|
|
2
|
+
|
|
3
|
+
export async function sendSpaceInboxMessage({
|
|
4
|
+
message,
|
|
5
|
+
spaceId,
|
|
6
|
+
inboxId,
|
|
7
|
+
encryptionPublicKey,
|
|
8
|
+
signaturePrivateKey,
|
|
9
|
+
authorAccountAddress,
|
|
10
|
+
syncServerUri,
|
|
11
|
+
}: Readonly<{
|
|
12
|
+
message: string;
|
|
13
|
+
spaceId: string;
|
|
14
|
+
inboxId: string;
|
|
15
|
+
encryptionPublicKey: string;
|
|
16
|
+
signaturePrivateKey: string | null;
|
|
17
|
+
authorAccountAddress: string | null;
|
|
18
|
+
syncServerUri: string;
|
|
19
|
+
}>) {
|
|
20
|
+
const messageToSend = await prepareSpaceInboxMessage({
|
|
21
|
+
message,
|
|
22
|
+
spaceId,
|
|
23
|
+
inboxId,
|
|
24
|
+
encryptionPublicKey,
|
|
25
|
+
signaturePrivateKey,
|
|
26
|
+
authorAccountAddress,
|
|
27
|
+
});
|
|
28
|
+
const res = await fetch(new URL(`/spaces/${spaceId}/inboxes/${inboxId}/messages`, syncServerUri), {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
headers: {
|
|
31
|
+
'Content-Type': 'application/json',
|
|
32
|
+
},
|
|
33
|
+
body: JSON.stringify(messageToSend),
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
throw new Error('Failed to send message');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function sendAccountInboxMessage({
|
|
41
|
+
message,
|
|
42
|
+
accountAddress,
|
|
43
|
+
inboxId,
|
|
44
|
+
encryptionPublicKey,
|
|
45
|
+
signaturePrivateKey,
|
|
46
|
+
authorAccountAddress,
|
|
47
|
+
syncServerUri,
|
|
48
|
+
}: Readonly<{
|
|
49
|
+
message: string;
|
|
50
|
+
accountAddress: string;
|
|
51
|
+
inboxId: string;
|
|
52
|
+
encryptionPublicKey: string;
|
|
53
|
+
signaturePrivateKey: string | null;
|
|
54
|
+
authorAccountAddress: string | null;
|
|
55
|
+
syncServerUri: string;
|
|
56
|
+
}>) {
|
|
57
|
+
const messageToSend = await prepareAccountInboxMessage({
|
|
58
|
+
message,
|
|
59
|
+
accountAddress,
|
|
60
|
+
inboxId,
|
|
61
|
+
encryptionPublicKey,
|
|
62
|
+
signaturePrivateKey,
|
|
63
|
+
authorAccountAddress,
|
|
64
|
+
});
|
|
65
|
+
const res = await fetch(new URL(`/accounts/${accountAddress}/inboxes/${inboxId}/messages`, syncServerUri), {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
},
|
|
70
|
+
body: JSON.stringify(messageToSend),
|
|
71
|
+
});
|
|
72
|
+
if (!res.ok) {
|
|
73
|
+
throw new Error('Failed to send message');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema';
|
|
2
|
+
|
|
3
|
+
export const InboxSenderAuthPolicy = Schema.Union(
|
|
4
|
+
Schema.Literal('anonymous'),
|
|
5
|
+
Schema.Literal('optional_auth'),
|
|
6
|
+
Schema.Literal('requires_auth'),
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export type InboxSenderAuthPolicy = Schema.Schema.Type<typeof InboxSenderAuthPolicy>;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * as Connect from './connect/index.js';
|
|
2
|
+
export * as Entity from './entity/index.js';
|
|
3
|
+
export * as Identity from './identity/index.js';
|
|
4
|
+
export * as Inboxes from './inboxes/index.js';
|
|
5
|
+
export * as Key from './key/index.js';
|
|
6
|
+
export * as Messages from './messages/index.js';
|
|
7
|
+
export * as SpaceEvents from './space-events/index.js';
|
|
8
|
+
export * as SpaceInfo from './space-info/index.js';
|
|
9
|
+
export * as StoreConnect from './store-connect.js';
|
|
10
|
+
export * from './store.js';
|
|
11
|
+
export * as Type from './type/type.js';
|
|
12
|
+
export * from './types.js';
|
|
13
|
+
export * as Utils from './utils/index.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { randomBytes } from '@noble/ciphers/webcrypto';
|
|
2
|
+
import { encryptKey } from './encrypt-key.js';
|
|
3
|
+
|
|
4
|
+
type Params = {
|
|
5
|
+
privateKey: Uint8Array;
|
|
6
|
+
publicKey: Uint8Array;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function createKey({ privateKey, publicKey }: Params): {
|
|
10
|
+
key: Uint8Array;
|
|
11
|
+
keyBoxCiphertext: Uint8Array;
|
|
12
|
+
keyBoxNonce: Uint8Array;
|
|
13
|
+
} {
|
|
14
|
+
const key = randomBytes(32);
|
|
15
|
+
|
|
16
|
+
const { keyBoxCiphertext, keyBoxNonce } = encryptKey({
|
|
17
|
+
key,
|
|
18
|
+
publicKey,
|
|
19
|
+
privateKey,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
key,
|
|
24
|
+
keyBoxCiphertext,
|
|
25
|
+
keyBoxNonce,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { decryptKeyBox } from './key-box.js';
|
|
2
|
+
|
|
3
|
+
type Params = {
|
|
4
|
+
privateKey: Uint8Array;
|
|
5
|
+
publicKey: Uint8Array;
|
|
6
|
+
keyBoxCiphertext: Uint8Array;
|
|
7
|
+
keyBoxNonce: Uint8Array;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function decryptKey({ privateKey, publicKey, keyBoxNonce, keyBoxCiphertext }: Params): Uint8Array {
|
|
11
|
+
const key = decryptKeyBox({
|
|
12
|
+
nonce: keyBoxNonce,
|
|
13
|
+
ciphertext: keyBoxCiphertext,
|
|
14
|
+
publicKey,
|
|
15
|
+
secretKey: privateKey,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return key;
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { randomBytes } from '@noble/ciphers/webcrypto';
|
|
2
|
+
import { encryptKeyBox } from './key-box.js';
|
|
3
|
+
|
|
4
|
+
type Params = {
|
|
5
|
+
privateKey: Uint8Array;
|
|
6
|
+
publicKey: Uint8Array;
|
|
7
|
+
key: Uint8Array;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function encryptKey({ privateKey, publicKey, key }: Params): {
|
|
11
|
+
keyBoxCiphertext: Uint8Array;
|
|
12
|
+
keyBoxNonce: Uint8Array;
|
|
13
|
+
} {
|
|
14
|
+
const nonce = randomBytes(24);
|
|
15
|
+
|
|
16
|
+
const ciphertext = encryptKeyBox({
|
|
17
|
+
message: key,
|
|
18
|
+
nonce,
|
|
19
|
+
publicKey,
|
|
20
|
+
secretKey: privateKey,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
keyBoxCiphertext: ciphertext,
|
|
25
|
+
keyBoxNonce: nonce,
|
|
26
|
+
};
|
|
27
|
+
}
|
package/src/key/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { cryptoBoxEasy, cryptoBoxKeyPair, cryptoBoxOpenEasy } from '@serenity-kit/noble-sodium';
|
|
2
|
+
|
|
3
|
+
export function generateKeypair(): {
|
|
4
|
+
publicKey: Uint8Array;
|
|
5
|
+
secretKey: Uint8Array;
|
|
6
|
+
} {
|
|
7
|
+
const { publicKey, privateKey } = cryptoBoxKeyPair();
|
|
8
|
+
return { publicKey, secretKey: privateKey };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type EncryptKeyBoxParams = {
|
|
12
|
+
message: Uint8Array;
|
|
13
|
+
nonce: Uint8Array;
|
|
14
|
+
publicKey: Uint8Array;
|
|
15
|
+
secretKey: Uint8Array;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type DecryptKeyBoxParams = {
|
|
19
|
+
ciphertext: Uint8Array;
|
|
20
|
+
nonce: Uint8Array;
|
|
21
|
+
publicKey: Uint8Array;
|
|
22
|
+
secretKey: Uint8Array;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function encryptKeyBox({ message, publicKey, secretKey, nonce }: EncryptKeyBoxParams): Uint8Array {
|
|
26
|
+
return cryptoBoxEasy({ message, publicKey, privateKey: secretKey, nonce });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function decryptKeyBox({ ciphertext, nonce, publicKey, secretKey }: DecryptKeyBoxParams): Uint8Array {
|
|
30
|
+
return cryptoBoxOpenEasy({ ciphertext, publicKey, privateKey: secretKey, nonce });
|
|
31
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
|
|
2
|
+
|
|
3
|
+
interface Params {
|
|
4
|
+
nonceAndCiphertext: Uint8Array;
|
|
5
|
+
secretKey: Uint8Array;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function decryptMessage({ nonceAndCiphertext, secretKey }: Params) {
|
|
9
|
+
const nonce = nonceAndCiphertext.subarray(0, 24);
|
|
10
|
+
const ciphertext = nonceAndCiphertext.subarray(24);
|
|
11
|
+
const cipher = xchacha20poly1305(secretKey, nonce);
|
|
12
|
+
return cipher.decrypt(ciphertext);
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
|
|
2
|
+
import { randomBytes } from '@noble/ciphers/webcrypto';
|
|
3
|
+
|
|
4
|
+
type Params = {
|
|
5
|
+
message: Uint8Array;
|
|
6
|
+
secretKey: Uint8Array;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function encryptMessage({ message, secretKey }: Params) {
|
|
10
|
+
const nonce = randomBytes(24);
|
|
11
|
+
const cipher = xchacha20poly1305(secretKey, nonce);
|
|
12
|
+
const ciphertext = cipher.encrypt(message);
|
|
13
|
+
return new Uint8Array([...nonce, ...ciphertext]);
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// biome-ignore lint/suspicious/noExplicitAny: same as stringify
|
|
2
|
+
export function serialize(obj: any): string {
|
|
3
|
+
return JSON.stringify(obj, (_key, value) => {
|
|
4
|
+
if (value instanceof Uint8Array) {
|
|
5
|
+
return { __type: 'Uint8Array', data: Array.from(value) };
|
|
6
|
+
}
|
|
7
|
+
if (value instanceof Date) {
|
|
8
|
+
return { __type: 'Date', data: value.toISOString() };
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function deserialize(json: string): unknown {
|
|
15
|
+
return JSON.parse(json, (_key, value) => {
|
|
16
|
+
if (value && value.__type === 'Uint8Array') {
|
|
17
|
+
return value.data;
|
|
18
|
+
}
|
|
19
|
+
if (value && value.__type === 'Date') {
|
|
20
|
+
return new Date(value.data);
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
+
import { bytesToHex, canonicalize, hexToBytes, stringToUint8Array } from '../utils/index.js';
|
|
4
|
+
import { encryptMessage } from './encrypt-message.js';
|
|
5
|
+
import type { RequestCreateUpdate } from './types.js';
|
|
6
|
+
|
|
7
|
+
interface SignedMessageParams {
|
|
8
|
+
accountAddress: string;
|
|
9
|
+
updateId: string;
|
|
10
|
+
spaceId: string;
|
|
11
|
+
message: Uint8Array;
|
|
12
|
+
secretKey: string;
|
|
13
|
+
signaturePrivateKey: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface RecoverParams {
|
|
17
|
+
update: Uint8Array;
|
|
18
|
+
spaceId: string;
|
|
19
|
+
updateId: string;
|
|
20
|
+
signature: {
|
|
21
|
+
hex: string;
|
|
22
|
+
recovery: number;
|
|
23
|
+
};
|
|
24
|
+
accountAddress: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const signedUpdateMessage = ({
|
|
28
|
+
accountAddress,
|
|
29
|
+
updateId,
|
|
30
|
+
spaceId,
|
|
31
|
+
message,
|
|
32
|
+
secretKey,
|
|
33
|
+
signaturePrivateKey,
|
|
34
|
+
}: SignedMessageParams): RequestCreateUpdate => {
|
|
35
|
+
const update = encryptMessage({
|
|
36
|
+
message,
|
|
37
|
+
secretKey: hexToBytes(secretKey),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const messageToSign = stringToUint8Array(
|
|
41
|
+
canonicalize({
|
|
42
|
+
accountAddress,
|
|
43
|
+
updateId,
|
|
44
|
+
update,
|
|
45
|
+
spaceId,
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const recoverySignature = secp256k1.sign(messageToSign, hexToBytes(signaturePrivateKey), { prehash: true });
|
|
50
|
+
|
|
51
|
+
const signature = {
|
|
52
|
+
hex: recoverySignature.toCompactHex(),
|
|
53
|
+
recovery: recoverySignature.recovery,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
type: 'create-update',
|
|
58
|
+
updateId,
|
|
59
|
+
update,
|
|
60
|
+
spaceId,
|
|
61
|
+
accountAddress,
|
|
62
|
+
signature,
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const recoverUpdateMessageSigner = ({
|
|
67
|
+
update,
|
|
68
|
+
spaceId,
|
|
69
|
+
updateId,
|
|
70
|
+
signature,
|
|
71
|
+
accountAddress,
|
|
72
|
+
}: RecoverParams | RequestCreateUpdate) => {
|
|
73
|
+
const recoveredSignature = secp256k1.Signature.fromCompact(signature.hex).addRecoveryBit(signature.recovery);
|
|
74
|
+
const signedMessage = stringToUint8Array(
|
|
75
|
+
canonicalize({
|
|
76
|
+
accountAddress,
|
|
77
|
+
updateId,
|
|
78
|
+
update,
|
|
79
|
+
spaceId,
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
const signedMessageHash = sha256(signedMessage);
|
|
83
|
+
return bytesToHex(recoveredSignature.recoverPublicKey(signedMessageHash).toRawBytes(true));
|
|
84
|
+
};
|