UNPKG

@iotize/tap

Version:

IoTize Device client for Javascript

135 lines 10.9 kB
import '../generated/converter-stream-extension'; import { bufferToHexString } from '@iotize/common/byte-converter'; import { AesEcb128Converter } from '@iotize/common/crypto'; import { ScramAuth } from '@iotize/tap/auth'; import { TapStreamReader, TapStreamWriter } from '@iotize/tap/client/impl'; import { DefaultSinglePacketKeyGenerator } from './single-packet-key-generator'; const TAG = 'SinglePacket'; TapStreamReader.prototype.readSinglePacketPayloadFullData = function () { const model = {}; model.logTime = this.readU4(); model.dataSize = this.readU2(); model.data = this.readBytes(-4); model.crc = this.readU4(); return model; }; export class SinglePacketEncryptionOptionsBuilder { static fromBlankKey(username) { return { hashKey: new Uint8Array(32), serialNumber: 'IoTize_FWUpdate_SP', username, }; } static fromHashKey(hashKey, username) { return { hashKey, serialNumber: 'IoTize_FWUpdate_SP', username, }; } static fromUserCredentials(credentials, options) { const keys = ScramAuth.computeBaseKeys(credentials.password, options); return SinglePacketEncryptionOptionsBuilder.fromCurrentSessionData({ username: credentials.username, serverKey: keys.serverKey, storedKey: keys.storedKey, }); } static fromCurrentSessionData(sessionData) { const hashKey = TapStreamWriter.create(32) .writeBytes(sessionData.storedKey) .writeBytes(sessionData.serverKey).toBytes; if (hashKey.length !== 32) { // TODO constant throw new Error(`Single packet encryption not available`); } return { hashKey, serialNumber: 'IoTize_FWUpdate_SP', username: sessionData.username, }; } } export class EncryptedSinglePacketConverter { constructor(options, encryptionAlgo = new AesEcb128Converter(), keyGenerator = new DefaultSinglePacketKeyGenerator()) { this.options = options; this.encryptionAlgo = encryptionAlgo; this.keyGenerator = keyGenerator; } static createWithBlankKey() { return new EncryptedSinglePacketConverter(SinglePacketEncryptionOptionsBuilder.fromBlankKey('IoTize')); } setEncryptionOptions(options) { this.options = Object.assign(Object.assign({}, this.options), options); } encode(packet) { const stream = new TapStreamWriter(); stream.writeU4(packet.sendTime); stream.writeSinglePacketHeader(packet.header); const payloadBytesPosition = stream.pos; stream.writeSinglePacketPayload(packet.payload); if (packet.header.encryption) { const bytes = stream.toBytes; // debug(`SinglePacket before encryption: ${toHexString(bytes)}`); const encryptionAlgo = this._getEncryptionAlgo(packet.header); let encryptedPayloadBytes = bytes.slice(payloadBytesPosition); encryptedPayloadBytes = encryptionAlgo.encode(encryptedPayloadBytes); stream.pos = payloadBytesPosition; stream.writeBytes(encryptedPayloadBytes); } return stream.toBytes; } decode(packetData) { const stream = TapStreamReader.fromArray(packetData); const sendTime = stream.readU4(); const header = stream.readSinglePacketHeader(); let payload; if (header.encryption) { const encryptedData = stream.readBytesFull(); const encryptionAlgo = this._getEncryptionAlgo(header); const decryptedData = encryptionAlgo.decode(encryptedData); const payloadStream = TapStreamReader.fromArray(decryptedData); // if (header.messageType == SinglePacketModel.PacketType.CODE_EXEC) { payload = payloadStream.readSinglePacketPayloadFullData(); // } else { // payload = payloadStream.readSinglePacketPayload(); // } } else { payload = stream.readSinglePacketPayload(); } const packet = { sendTime, header: header, payload, }; // TODO check CRC // let computedCrc = 0; // if (computedCrc !== packet.payload.crc){ // CRC.fromBytes() // } return packet; } _getEncryptionAlgo(header) { const encryptionKey = this.computeKey(header); this.encryptionAlgo.setOptions({ iv: '00000000000000000000000000000000', key: bufferToHexString(encryptionKey), }); return this.encryptionAlgo; } computeKey(header) { if (!(header instanceof Uint8Array)) { const stream = new TapStreamWriter(12); header = stream.writeSinglePacketHeader(header).toBytes; } const generateOptions = Object.assign(Object.assign({}, this.options), { headerBytes: header, }); const key = this.keyGenerator.generate(generateOptions); return key; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2luZ2xlLXBhY2tldC1jb252ZXJ0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zZXJ2aWNlL2ltcGwvc2luZ2xlLXBhY2tldC9zcmMvbGliL2N1c3RvbS9zaW5nbGUtcGFja2V0LWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLHlDQUF5QyxDQUFDO0FBRWpELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzNELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBSTNFLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRWhGLE1BQU0sR0FBRyxHQUFHLGNBQWMsQ0FBQztBQVEzQixlQUFlLENBQUMsU0FBUyxDQUFDLCtCQUErQjtJQUN2RDtRQUNFLE1BQU0sS0FBSyxHQUF1QyxFQUFFLENBQUM7UUFDckQsS0FBSyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDOUIsS0FBSyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDL0IsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEMsS0FBSyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDMUIsT0FBTyxLQUFrQyxDQUFDO0lBQzVDLENBQUMsQ0FBQztBQVVKLE1BQU0sT0FBTyxvQ0FBb0M7SUFDeEMsTUFBTSxDQUFDLFlBQVksQ0FBQyxRQUFnQjtRQUN6QyxPQUFPO1lBQ0wsT0FBTyxFQUFFLElBQUksVUFBVSxD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