-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathotr.message.js
159 lines (140 loc) · 4.41 KB
/
otr.message.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
* OTR Message Parser
* behave like a polymorph (properties are defined based on type)
*
* @author Khandar William
* @namespace Otr
*
* 2012-07-04 initial commit
* 2012-07-05 rough parsing, toString
* 2012-07-10 use ByteBuffer
* 2012-11-05 recognize fragmentation
*/
Otr.Message = (function () {
"use strict";
/**
* @param {String} msg an OTR message
*/
function Message(msg) {
var matches,
bytebuff;
if (!msg.match(/^\?OTR/)) {
// this is plaintext message
this.type = Message.MSG_PLAIN;
this.message = msg;
// @TODO check whitespace tag
} else if (msg === '?OTRv2?') {
// this is OTR Query Message
this.type = Message.MSG_QUERY;
this.message = msg;
} else if (matches = msg.match(/^\?OTR Error:(.*)$/)) {
// this is OTR Error Message
this.type = Message.MSG_ERROR;
this.message = matches[1];
} else if (matches = msg.match(/^\?OTR,(\d+),(\d+),(.+)\.?,$/)) {
this.type = Message.MSG_FRAGMENT;
this.message = msg;
} else if (matches = msg.match(/^\?OTR:([a-zA-Z0-9+\/]+={0,2})\.$/)) {
// message type is taken from content
bytebuff = Otr.ByteBuffer.fromBase64(matches[1]);
this.version = bytebuff.readShort();
this.type = bytebuff.readByte();
// parse message components
// properties name are prefixed with value type
switch (this.type) {
case Message.MSG_DH_COMMIT:
this.dataEncryptedGx = bytebuff.readData();
this.dataHashedGx = bytebuff.readData();
break;
case Message.MSG_DH_KEY:
this.mpiGy = bytebuff.readMPI();
break;
case Message.MSG_REVEAL_SIGNATURE:
this.dataRevealedKey = bytebuff.readData();
this.dataEncryptedSignature = bytebuff.readData();
this.macSignature = bytebuff.readBytes(20);
break;
case Message.MSG_SIGNATURE:
this.dataEncryptedSignature = bytebuff.readData();
this.macSignature = bytebuff.readBytes(20);
break;
case Message.MSG_DATA:
this.byteFlags = bytebuff.readByte();
this.intSenderKeyid = bytebuff.readUInt();
this.intRecipientKeyid = bytebuff.readUInt();
this.mpiDHy = bytebuff.readMPI();
this.ctr = bytebuff.readBytes(8);
this.dataEncryptedMessage = bytebuff.readData();
this.macAuthenticator = bytebuff.readBytes(20);
this.dataOldMacKeys = bytebuff.readData();
break;
default:
// unknown/invalid type
this.type = Message.MSG_UNKNOWN;
this.message = msg;
}
} else {
// I don't recognize this
this.type = Message.MSG_UNKNOWN;
this.message = msg;
}
}
// constants
Message.MSG_UNKNOWN = -99;
Message.MSG_QUERY = -1;
Message.MSG_ERROR = -2;
Message.MSG_PLAIN = -3;
Message.MSG_FRAGMENT = -4;
// specified by protocol:
Message.MSG_DH_COMMIT = 0x02;
Message.MSG_DH_KEY = 0x0a;
Message.MSG_REVEAL_SIGNATURE = 0x11;
Message.MSG_SIGNATURE = 0x12;
Message.MSG_DATA = 0x03;
Message.prototype = {
type: 0, // SHORT 16-bit unsigned
version: 2, // BYTE 8-bit unsigned
message: '',
// properties are dinamically created based on message type
// @TODO complete properties
toString: function () {
var bytebuff = new Otr.ByteBuffer();
bytebuff.writeShort(this.version);
bytebuff.writeByte(this.type);
switch (this.type) {
case Message.MSG_ERROR:
return '?OTR Error:'+this.message;
case Message.MSG_DH_COMMIT:
bytebuff.writeData(this.dataEncryptedGx);
bytebuff.writeData(this.dataHashedGx);
break;
case Message.MSG_DH_KEY:
bytebuff.writeMPI(this.mpiGy);
break;
case Message.MSG_REVEAL_SIGNATURE:
bytebuff.writeData(this.dataRevealedKey);
bytebuff.writeData(this.dataEncryptedSignature);
bytebuff.writeBytes(this.macSignature, 20);
break;
case Message.MSG_SIGNATURE:
bytebuff.writeData(this.dataEncryptedSignature);
bytebuff.writeBytes(this.macSignature, 20);
break;
case Message.MSG_DATA:
bytebuff.writeByte(this.byteFlags);
bytebuff.writeUInt(this.intSenderKeyid);
bytebuff.writeUInt(this.intRecipientKeyid);
bytebuff.writeMPI(this.mpiDHy);
bytebuff.writeBytes(this.ctr, 8);
bytebuff.writeData(this.dataEncryptedMessage);
bytebuff.writeBytes(this.macAuthenticator, 20);
bytebuff.writeData(this.dataOldMacKeys);
break;
default:
return this.message;
}
return '?OTR:'+(bytebuff.toBase64())+'.';
}
};
return Message;
}());