encryptFileInfo encrypts a FileInfo and wraps it into a new fake FileInfo with an encrypted name.
(keyGen *KeyGenerator, fi FileInfo, folderKey *[keySize]byte)
| 287 | // encryptFileInfo encrypts a FileInfo and wraps it into a new fake FileInfo |
| 288 | // with an encrypted name. |
| 289 | func encryptFileInfo(keyGen *KeyGenerator, fi FileInfo, folderKey *[keySize]byte) FileInfo { |
| 290 | fileKey := keyGen.FileKey(fi.Name, folderKey) |
| 291 | |
| 292 | // The entire FileInfo is encrypted with a random nonce, and concatenated |
| 293 | // with that nonce. |
| 294 | |
| 295 | bs, err := proto.Marshal(fi.ToWire(false)) |
| 296 | if err != nil { |
| 297 | panic("impossible serialization mishap: " + err.Error()) |
| 298 | } |
| 299 | encryptedFI := encryptBytes(bs, fileKey) |
| 300 | |
| 301 | // The vector is set to something that is higher than any other version sent |
| 302 | // previously. We do this because |
| 303 | // there is no way for the insecure device on the other end to do proper |
| 304 | // conflict resolution, so they will simply accept and keep whatever is the |
| 305 | // latest version they see. The secure devices will decrypt the real |
| 306 | // FileInfo, see the real Version, and act appropriately regardless of what |
| 307 | // this fake version happens to be. |
| 308 | // The vector also needs to be deterministic/the same among all trusted |
| 309 | // devices with the same vector, such that the pulling/remote completion |
| 310 | // works correctly on the untrusted device(s). |
| 311 | |
| 312 | version := Vector{ |
| 313 | Counters: []Counter{ |
| 314 | { |
| 315 | ID: 1, |
| 316 | }, |
| 317 | }, |
| 318 | } |
| 319 | for _, counter := range fi.Version.Counters { |
| 320 | version.Counters[0].Value += counter.Value |
| 321 | } |
| 322 | |
| 323 | // Construct the fake block list. Each block will be blockOverhead bytes |
| 324 | // larger than the corresponding real one and have an encrypted hash. |
| 325 | // Very small blocks will be padded upwards to minPaddedSize. |
| 326 | // |
| 327 | // The encrypted hash becomes just a "token" for the data -- it doesn't |
| 328 | // help verifying it, but it lets the encrypted device do block level |
| 329 | // diffs and data reuse properly when it gets a new version of a file. |
| 330 | |
| 331 | var offset int64 |
| 332 | blocks := make([]BlockInfo, len(fi.Blocks)) |
| 333 | for i, b := range fi.Blocks { |
| 334 | if b.Size < minPaddedSize { |
| 335 | b.Size = minPaddedSize |
| 336 | } |
| 337 | size := b.Size + blockOverhead |
| 338 | hash := encryptBlockHash(b.Hash, b.Offset, fileKey) |
| 339 | blocks[i] = BlockInfo{ |
| 340 | Hash: hash, |
| 341 | Offset: offset, |
| 342 | Size: size, |
| 343 | } |
| 344 | offset += int64(size) |
| 345 | } |
| 346 |