@iotize/tap
Version:
IoTize Device client for Javascript
135 lines • 10.9 kB
JavaScript
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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