on master help sign in
Remove payload versioning and schema migrations
fc75d89iko
client/Constants.fs−1
@@ -10,7 +10,6 @@ module Constants =
10 let hkdfInfo = "skrepka-v1"
10 let hkdfInfo = "skrepka-v1"
11 let profileId = "me"
11 let profileId = "me"
12 let settingsId = "settings"
12 let settingsId = "settings"
13− let schemaVersion = 2
14 let maxBitmapCacheSize = 128
13 let maxBitmapCacheSize = 128
15 let pollRetryBaseMs = 3000
14 let pollRetryBaseMs = 3000
16 let outboxRetryDelayMs = 3000
15 let outboxRetryDelayMs = 3000
client/Crypto.fs+18−48
@@ -178,16 +178,14 @@ module Crypto =
178 let info = Encoding.UTF8.GetBytes(Constants.hkdfInfo)
178 let info = Encoding.UTF8.GetBytes(Constants.hkdfInfo)
179 HKDF.DeriveKey(HashAlgorithmName.SHA256, rawSecret, 32, salt, info)
179 HKDF.DeriveKey(HashAlgorithmName.SHA256, rawSecret, 32, salt, info)
180
180
181− // Blob layout v2: [ephPub(32) | nonce(24) | ciphertext]
181+ // Blob layout: [ephPub(32) | nonce(24) | ciphertext]
182 // encrypted payload: [senderPub(32) | signature(64) | compressed]
182 // encrypted payload: [senderPub(32) | signature(64) | compressed]
183 // signature signs (recipientPub ++ compressed) — prevents forwarding
183 // signature signs (recipientPub ++ compressed) — prevents forwarding
184− // Legacy layout: [ephPub(32) | nonce(24) | ciphertext | senderPub(32) | signature(64)]
185 let private ephPubLen = 32
184 let private ephPubLen = 32
186 let private nonceLen = 24
185 let private nonceLen = 24
187 let private pubLen = 32
186 let private pubLen = 32
188 let private sigLen = 64
187 let private sigLen = 64
189 let private headerLen = ephPubLen + nonceLen
188 let private headerLen = ephPubLen + nonceLen
190− let private legacyTrailerLen = pubLen + sigLen
191 let private minBlobLen = headerLen + pubLen + sigLen + 16 // inner fields + AEAD tag
189 let private minBlobLen = headerLen + pubLen + sigLen + 16 // inner fields + AEAD tag
192
190
193 let private deriveSymKey recipientPrivKey ephPub =
191 let private deriveSymKey recipientPrivKey ephPub =
@@ -226,50 +224,22 @@ module Crypto =
226 else
224 else
227 let ephPub = blob.[.. ephPubLen - 1]
225 let ephPub = blob.[.. ephPubLen - 1]
228 let nonce = blob.[ephPubLen .. headerLen - 1]
226 let nonce = blob.[ephPubLen .. headerLen - 1]
227+ let ciphertext = blob.[headerLen ..]
228+ let key = deriveSymKey recipientPrivKey ephPub
229+ let decrypted = aeadDecrypt ciphertext nonce key
229
230
230− // Try v2 format: entire payload after header is ciphertext
231− let v2Result =
232− try
233− let ciphertext = blob.[headerLen ..]
234− let key = deriveSymKey recipientPrivKey ephPub
235− let decrypted = aeadDecrypt ciphertext nonce key
236−
237− if decrypted.Length < pubLen + sigLen then
231+ if decrypted.Length < pubLen + sigLen then
238− None
232+ None
239− else
233+ else
240− let senderPub = decrypted.[.. pubLen - 1]
234+ let senderPub = decrypted.[.. pubLen - 1]
241− let signature = decrypted.[pubLen .. pubLen + sigLen - 1]
235+ let signature = decrypted.[pubLen .. pubLen + sigLen - 1]
242− let compressed = decrypted.[pubLen + sigLen ..]
236+ let compressed = decrypted.[pubLen + sigLen ..]
243−
237+
244− let recipientPub = recipientPrivKey.[32..63]
238+ let recipientPub = recipientPrivKey.[32..63]
245− let signedData = Array.append recipientPub compressed
239+ let signedData = Array.append recipientPub compressed
246−
240+
247− if verifyDetached signature signedData senderPub then
241+ if verifyDetached signature signedData senderPub then
248− let plaintext = LZ4Pickler.Unpickle(compressed)
242+ let plaintext = LZ4Pickler.Unpickle(compressed)
249− Some(Encoding.UTF8.GetString(plaintext), toHex senderPub)
243+ Some(Encoding.UTF8.GetString(plaintext), toHex senderPub)
250− else
251− None
252− with _ -> None
253−
254− match v2Result with
255− | Some _ -> v2Result
256− | None ->
257− // Fall back to legacy format: trailer has senderPub + signature in plaintext
258− try
259− if blob.Length < headerLen + 16 + legacyTrailerLen then
260− None
261− else
262− let ciphertext = blob.[headerLen .. blob.Length - legacyTrailerLen - 1]
263− let senderPub = blob.[blob.Length - legacyTrailerLen .. blob.Length - sigLen - 1]
264− let signature = blob.[blob.Length - sigLen ..]
265−
266− if not (verifyDetached signature ciphertext senderPub) then
267− None
268− else
244+ else
269− let key = deriveSymKey recipientPrivKey ephPub
270− let decrypted = aeadDecrypt ciphertext nonce key
271− let plaintext = LZ4Pickler.Unpickle(decrypted)
272− Some(Encoding.UTF8.GetString(plaintext), toHex senderPub)
273− with ex ->
274− log $"decrypt error: {ex.Message}"
275 None
245 None
client/Store.fs+1−23
@@ -137,29 +137,7 @@ module Store =
137 |> Db.exec
137 |> Db.exec
138
138
139 conn
139 conn
140− |> Db.newCommand "CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)"
141− |> Db.exec
142−
143− let dbVersion =
144− try
145− conn
146− |> Db.newCommand "SELECT value FROM schema_meta WHERE key = 'schema_version'"
147− |> Db.querySingle (fun rd -> rd.ReadString "value" |> int)
148− |> Option.defaultValue 0
149− with ex ->
150− log $"schema version check: {ex.Message}"
151− 0
152−
153− if dbVersion < 2 then
154− conn
155− |> Db.newCommand "CREATE INDEX IF NOT EXISTS idx_messages_conv ON messages(ConversationId)"
140+ |> Db.newCommand "CREATE INDEX IF NOT EXISTS idx_messages_conv ON messages(ConversationId)"
156− |> Db.exec
157−
158− conn
159− |> Db.newCommand "INSERT OR REPLACE INTO schema_meta (key, value) VALUES (@key, @value)"
160− |> Db.setParams
161− [ "key", SqlType.String "schema_version"
162− "value", SqlType.String(string Constants.schemaVersion) ]
163 |> Db.exec
141 |> Db.exec
164
142
165 // ── Identity ──
143 // ── Identity ──