@signalapp/mock-server
Advanced tools
Comparing version 4.0.1 to 4.1.0
{ | ||
"name": "@signalapp/mock-server", | ||
"version": "4.0.1", | ||
"version": "4.1.0", | ||
"description": "Mock Signal Server for writing tests", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -310,2 +310,6 @@ "use strict"; | ||
await super.updateDeviceKeys(device, serviceIdKind, keys); | ||
// Atomic linking updates only signed pre keys, and we should ignore it. | ||
if (!keys.preKeys?.length && !keys.kyberPreKeys?.length) { | ||
return; | ||
} | ||
const key = `${device.aci}.${device.getRegistrationId(serviceIdKind)}`; | ||
@@ -312,0 +316,0 @@ // Device is marked as provisioned only once we have its keys |
@@ -6,3 +6,4 @@ /// <reference types="node" /> | ||
import { Attachment } from './data/attachment'; | ||
import { AciString, DeviceId } from './types'; | ||
import type { ServerPreKey, ServerSignedPreKey } from './data/schemas'; | ||
import { AciString, DeviceId, KyberPreKey, PreKey, SignedPreKey } from './types'; | ||
export type EncryptedProvisionMessage = { | ||
@@ -34,1 +35,4 @@ body: Buffer; | ||
export declare function generateAccessKeyVerifier(accessKey: Buffer): Buffer; | ||
export declare function decodePreKey({ keyId, publicKey, }: ServerPreKey): PreKey; | ||
export declare function decodeSignedPreKey({ keyId, publicKey, signature, }: ServerSignedPreKey): SignedPreKey; | ||
export declare function decodeKyberPreKey({ keyId, publicKey, signature, }: ServerSignedPreKey): KyberPreKey; |
@@ -8,3 +8,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generateAccessKeyVerifier = exports.encryptProfileName = exports.encryptStorageItem = exports.decryptStorageItem = exports.encryptStorageManifest = exports.decryptStorageManifest = exports.deriveAccessKey = exports.generateSenderCertificate = exports.generateServerCertificate = exports.encryptAttachment = exports.encryptProvisionMessage = void 0; | ||
exports.decodeKyberPreKey = exports.decodeSignedPreKey = exports.decodePreKey = exports.generateAccessKeyVerifier = exports.encryptProfileName = exports.encryptStorageItem = exports.decryptStorageItem = exports.encryptStorageManifest = exports.decryptStorageManifest = exports.deriveAccessKey = exports.generateSenderCertificate = exports.generateServerCertificate = exports.encryptAttachment = exports.encryptProvisionMessage = void 0; | ||
const crypto_1 = __importDefault(require("crypto")); | ||
@@ -216,1 +216,24 @@ const buffer_1 = require("buffer"); | ||
exports.generateAccessKeyVerifier = generateAccessKeyVerifier; | ||
function decodePreKey({ keyId, publicKey, }) { | ||
return { | ||
keyId, | ||
publicKey: libsignal_client_1.PublicKey.deserialize(buffer_1.Buffer.from(publicKey, 'base64')), | ||
}; | ||
} | ||
exports.decodePreKey = decodePreKey; | ||
function decodeSignedPreKey({ keyId, publicKey, signature, }) { | ||
return { | ||
keyId, | ||
publicKey: libsignal_client_1.PublicKey.deserialize(buffer_1.Buffer.from(publicKey, 'base64')), | ||
signature: buffer_1.Buffer.from(signature, 'base64'), | ||
}; | ||
} | ||
exports.decodeSignedPreKey = decodeSignedPreKey; | ||
function decodeKyberPreKey({ keyId, publicKey, signature, }) { | ||
return { | ||
keyId, | ||
publicKey: libsignal_client_1.KEMPublicKey.deserialize(buffer_1.Buffer.from(publicKey, 'base64')), | ||
signature: buffer_1.Buffer.from(signature, 'base64'), | ||
}; | ||
} | ||
exports.decodeKyberPreKey = decodeKyberPreKey; |
@@ -66,3 +66,4 @@ "use strict"; | ||
debug('setting %s keys for %s', serviceIdKind, this.debugId); | ||
const { signedPreKey, lastResortKey } = keys; | ||
const existingKeys = this.keys.get(serviceIdKind); | ||
const { signedPreKey = existingKeys?.signedPreKey, lastResortKey = existingKeys?.lastResortKey, } = keys; | ||
if (!signedPreKey) { | ||
@@ -69,0 +70,0 @@ throw new Error('setKeys: Missing signedPreKey'); |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import z from 'zod'; | ||
@@ -9,2 +8,13 @@ import { AciString, DeviceId, PniString, RegistrationId } from '../types'; | ||
export declare const DeviceIdSchema: z.ZodEffects<z.ZodNumber, DeviceId, number>; | ||
declare const PreKeySchema: z.ZodObject<{ | ||
keyId: z.ZodNumber; | ||
publicKey: z.ZodString; | ||
}, "strip", z.ZodTypeAny, { | ||
keyId: number; | ||
publicKey: string; | ||
}, { | ||
keyId: number; | ||
publicKey: string; | ||
}>; | ||
export type ServerPreKey = z.infer<typeof PreKeySchema>; | ||
declare const SignedPreKeySchema: z.ZodObject<{ | ||
@@ -172,11 +182,128 @@ keyId: z.ZodNumber; | ||
export type MessageList = z.infer<typeof MessageListSchema>; | ||
export declare const RegistrationDataSchema: z.ZodObject<{ | ||
registrationId: z.ZodEffects<z.ZodNumber, RegistrationId, number>; | ||
pniRegistrationId: z.ZodEffects<z.ZodNumber, RegistrationId, number>; | ||
export declare const AtomicLinkingDataSchema: z.ZodObject<{ | ||
verificationCode: z.ZodString; | ||
accountAttributes: z.ZodObject<{ | ||
fetchesMessages: z.ZodBoolean; | ||
registrationId: z.ZodEffects<z.ZodNumber, RegistrationId, number>; | ||
pniRegistrationId: z.ZodEffects<z.ZodNumber, RegistrationId, number>; | ||
name: z.ZodString; | ||
}, "strip", z.ZodTypeAny, { | ||
fetchesMessages: boolean; | ||
registrationId: RegistrationId; | ||
pniRegistrationId: RegistrationId; | ||
name: string; | ||
}, { | ||
fetchesMessages: boolean; | ||
registrationId: number; | ||
pniRegistrationId: number; | ||
name: string; | ||
}>; | ||
aciSignedPreKey: z.ZodObject<{ | ||
keyId: z.ZodNumber; | ||
publicKey: z.ZodString; | ||
signature: z.ZodString; | ||
}, "strip", z.ZodTypeAny, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}>; | ||
pniSignedPreKey: z.ZodObject<{ | ||
keyId: z.ZodNumber; | ||
publicKey: z.ZodString; | ||
signature: z.ZodString; | ||
}, "strip", z.ZodTypeAny, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}>; | ||
aciPqLastResortPreKey: z.ZodObject<{ | ||
keyId: z.ZodNumber; | ||
publicKey: z.ZodString; | ||
signature: z.ZodString; | ||
}, "strip", z.ZodTypeAny, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}>; | ||
pniPqLastResortPreKey: z.ZodObject<{ | ||
keyId: z.ZodNumber; | ||
publicKey: z.ZodString; | ||
signature: z.ZodString; | ||
}, "strip", z.ZodTypeAny, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}, { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}>; | ||
}, "strip", z.ZodTypeAny, { | ||
registrationId: RegistrationId; | ||
pniRegistrationId: RegistrationId; | ||
verificationCode: string; | ||
accountAttributes: { | ||
fetchesMessages: boolean; | ||
registrationId: RegistrationId; | ||
pniRegistrationId: RegistrationId; | ||
name: string; | ||
}; | ||
aciSignedPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
pniSignedPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
aciPqLastResortPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
pniPqLastResortPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
}, { | ||
registrationId: number; | ||
pniRegistrationId: number; | ||
verificationCode: string; | ||
accountAttributes: { | ||
fetchesMessages: boolean; | ||
registrationId: number; | ||
pniRegistrationId: number; | ||
name: string; | ||
}; | ||
aciSignedPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
pniSignedPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
aciPqLastResortPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
pniPqLastResortPreKey: { | ||
keyId: number; | ||
publicKey: string; | ||
signature: string; | ||
}; | ||
}>; | ||
@@ -183,0 +310,0 @@ export declare const GroupStateSchema: z.ZodObject<{ |
@@ -8,3 +8,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.PutUsernameLinkSchema = exports.UsernameConfirmationSchema = exports.UsernameReservationSchema = exports.GroupStateSchema = exports.RegistrationDataSchema = exports.MessageListSchema = exports.MessageSchema = exports.DeviceKeysSchema = exports.DeviceIdSchema = exports.RegistrationIdSchema = exports.ServiceIdSchema = exports.PniSchema = exports.AciSchema = void 0; | ||
exports.PutUsernameLinkSchema = exports.UsernameConfirmationSchema = exports.UsernameReservationSchema = exports.GroupStateSchema = exports.AtomicLinkingDataSchema = exports.MessageListSchema = exports.MessageSchema = exports.DeviceKeysSchema = exports.DeviceIdSchema = exports.RegistrationIdSchema = exports.ServiceIdSchema = exports.PniSchema = exports.AciSchema = void 0; | ||
const zod_1 = __importDefault(require("zod")); | ||
@@ -20,2 +20,6 @@ const util_1 = require("../util"); | ||
exports.DeviceIdSchema = zod_1.default.number().transform(x => x); | ||
const PreKeySchema = zod_1.default.object({ | ||
keyId: zod_1.default.number(), | ||
publicKey: zod_1.default.string(), | ||
}); | ||
const SignedPreKeySchema = zod_1.default.object({ | ||
@@ -28,6 +32,3 @@ keyId: zod_1.default.number(), | ||
identityKey: zod_1.default.string(), | ||
preKeys: zod_1.default.object({ | ||
keyId: zod_1.default.number(), | ||
publicKey: zod_1.default.string(), | ||
}).array(), | ||
preKeys: PreKeySchema.array(), | ||
pqPreKeys: SignedPreKeySchema.array().optional(), | ||
@@ -48,5 +49,14 @@ pqLastResortPreKey: SignedPreKeySchema.optional(), | ||
}); | ||
exports.RegistrationDataSchema = zod_1.default.object({ | ||
registrationId: exports.RegistrationIdSchema, | ||
pniRegistrationId: exports.RegistrationIdSchema, | ||
exports.AtomicLinkingDataSchema = zod_1.default.object({ | ||
verificationCode: zod_1.default.string(), | ||
accountAttributes: zod_1.default.object({ | ||
fetchesMessages: zod_1.default.boolean(), | ||
registrationId: exports.RegistrationIdSchema, | ||
pniRegistrationId: exports.RegistrationIdSchema, | ||
name: zod_1.default.string(), | ||
}), | ||
aciSignedPreKey: SignedPreKeySchema, | ||
pniSignedPreKey: SignedPreKeySchema, | ||
aciPqLastResortPreKey: SignedPreKeySchema, | ||
pniPqLastResortPreKey: SignedPreKeySchema, | ||
}); | ||
@@ -53,0 +63,0 @@ exports.GroupStateSchema = zod_1.default.object({ |
@@ -16,2 +16,3 @@ "use strict"; | ||
const debug_1 = __importDefault(require("debug")); | ||
const crypto_1 = require("../crypto"); | ||
const util_1 = require("../util"); | ||
@@ -53,24 +54,2 @@ const schemas_1 = require("../data/schemas"); | ||
// | ||
const provisionDevice = (0, microrouter_1.put)('/v1/devices/:code', async (req, res) => { | ||
const { error, username, password } = parsePassword(req); | ||
if (error) { | ||
return (0, micro_1.send)(res, 400, { error }); | ||
} | ||
if (!username || !password) { | ||
return (0, micro_1.send)(res, 400, { error: 'Invalid authorization header' }); | ||
} | ||
const body = schemas_1.RegistrationDataSchema.parse(await (0, micro_1.json)(req)); | ||
const device = await server.provisionDevice({ | ||
number: username, | ||
password, | ||
provisioningCode: req.params.code, | ||
registrationId: body.registrationId, | ||
pniRegistrationId: body.pniRegistrationId, | ||
}); | ||
return { | ||
deviceId: device.deviceId, | ||
uuid: device.aci, | ||
pni: (0, types_1.untagPni)(device.pni), | ||
}; | ||
}); | ||
// TODO: DESKTOP-5821 | ||
@@ -214,15 +193,2 @@ const getDeviceKeys = (0, microrouter_1.get)('/v2/keys/:serviceId/:deviceId', async (req, res) => { | ||
} | ||
function parseEllipticKey(base64) { | ||
return libsignal_client_1.PublicKey.deserialize(buffer_1.Buffer.from(base64, 'base64')); | ||
} | ||
function parseKyberKey(base64) { | ||
return libsignal_client_1.KEMPublicKey.deserialize(buffer_1.Buffer.from(base64, 'base64')); | ||
} | ||
function decodeKyberPreKey(key) { | ||
return { | ||
keyId: key.keyId, | ||
publicKey: parseKyberKey(key.publicKey), | ||
signature: buffer_1.Buffer.from(key.signature, 'base64'), | ||
}; | ||
} | ||
const putKeys = (0, microrouter_1.put)('/v2/keys', async (req, res) => { | ||
@@ -237,23 +203,10 @@ const device = await auth(req, res); | ||
await server.updateDeviceKeys(device, serviceIdKind, { | ||
identityKey: parseEllipticKey(body.identityKey), | ||
preKeys: body.preKeys | ||
? body.preKeys.map((preKey) => { | ||
return { | ||
keyId: preKey.keyId, | ||
publicKey: parseEllipticKey(preKey.publicKey), | ||
}; | ||
}) | ||
: undefined, | ||
kyberPreKeys: body.pqPreKeys | ||
? body.pqPreKeys.map(decodeKyberPreKey) | ||
: undefined, | ||
identityKey: libsignal_client_1.PublicKey.deserialize(buffer_1.Buffer.from(body.identityKey, 'base64')), | ||
preKeys: body.preKeys?.map(crypto_1.decodePreKey), | ||
kyberPreKeys: body.pqPreKeys?.map(crypto_1.decodeKyberPreKey), | ||
lastResortKey: body.pqLastResortPreKey | ||
? decodeKyberPreKey(body.pqLastResortPreKey) | ||
? (0, crypto_1.decodeKyberPreKey)(body.pqLastResortPreKey) | ||
: undefined, | ||
signedPreKey: body.signedPreKey | ||
? { | ||
keyId: body.signedPreKey.keyId, | ||
publicKey: parseEllipticKey(body.signedPreKey.publicKey), | ||
signature: buffer_1.Buffer.from(body.signedPreKey.signature, 'base64'), | ||
} | ||
? (0, crypto_1.decodeSignedPreKey)(body.signedPreKey) | ||
: undefined, | ||
@@ -520,3 +473,3 @@ }); | ||
// TODO(indutny): support nameless devices? They use different route | ||
provisionDevice, getDeviceKeys, getAllDeviceKeys, getAttachment, getStickerPack, getSticker, putKeys, getKeys, whoami, reserveUsername, confirmUsername, deleteUsername, lookupByUsernameHash, lookupByUsernameLink, replaceUsernameLink, putChallenge, | ||
getDeviceKeys, getAllDeviceKeys, getAttachment, getStickerPack, getSticker, putKeys, getKeys, whoami, reserveUsername, confirmUsername, deleteUsername, lookupByUsernameHash, lookupByUsernameLink, replaceUsernameLink, putChallenge, | ||
// Technically these should live on a separate server, but who cares | ||
@@ -523,0 +476,0 @@ getGroup, getGroupVersion, getGroupLogs, createGroup, modifyGroup, getStorageManifest, getStorageManifestByVersion, putStorage, putStorageRead, |
@@ -235,3 +235,3 @@ "use strict"; | ||
})); | ||
this.router.put('/v1/devices/:code', async (params, body, headers) => { | ||
this.router.put('/v1/devices/link', async (_params, body, headers) => { | ||
const { error, username, password } = (0, util_1.parseAuthHeader)(headers.authorization); | ||
@@ -247,10 +247,25 @@ if (error) { | ||
} | ||
const { registrationId, pniRegistrationId, } = schemas_1.RegistrationDataSchema.parse(JSON.parse(buffer_1.Buffer.from(body).toString())); | ||
const { verificationCode, accountAttributes, aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, } = schemas_1.AtomicLinkingDataSchema.parse(JSON.parse(buffer_1.Buffer.from(body).toString())); | ||
const { registrationId, pniRegistrationId, } = accountAttributes; | ||
const device = await server.provisionDevice({ | ||
number: username, | ||
password, | ||
provisioningCode: params.code, | ||
provisioningCode: verificationCode, | ||
registrationId, | ||
pniRegistrationId, | ||
}); | ||
const primary = await server.getDeviceByServiceId(device.aci); | ||
if (!primary) { | ||
throw new Error('Primary device not found'); | ||
} | ||
await server.updateDeviceKeys(device, types_1.ServiceIdKind.ACI, { | ||
identityKey: await primary.getIdentityKey(types_1.ServiceIdKind.ACI), | ||
lastResortKey: (0, crypto_2.decodeKyberPreKey)(aciPqLastResortPreKey), | ||
signedPreKey: (0, crypto_2.decodeSignedPreKey)(aciSignedPreKey), | ||
}); | ||
await server.updateDeviceKeys(device, types_1.ServiceIdKind.PNI, { | ||
identityKey: await primary.getIdentityKey(types_1.ServiceIdKind.PNI), | ||
lastResortKey: (0, crypto_2.decodeKyberPreKey)(pniPqLastResortPreKey), | ||
signedPreKey: (0, crypto_2.decodeSignedPreKey)(pniSignedPreKey), | ||
}); | ||
return [200, { | ||
@@ -257,0 +272,0 @@ deviceId: device.deviceId, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3595005
66518