docs: add TSDNS/file transfer designs, review p256 PR draft (TODO-057,066,067)

TSDNS: verified fully implemented in chanora_resolver (port 41144,
magic bytes, TCP query). File transfer: verified fully implemented
for avatars/icons (ftinitdownload, TCP data, cacache). p256 PR draft
reviewed and corrected (function path, probability figure).
This commit is contained in:
Edison Jwa
2026-06-11 21:44:31 +09:00
parent 602eedc029
commit fe3da41e41
3 changed files with 286 additions and 16 deletions
+30 -16
View File
@@ -18,25 +18,33 @@ P-256 coordinates must always be exactly 32 bytes (the field element size). Stri
## Fix
Zero-pad P-256 coordinates to 32 bytes after `BigInt::to_bytes_be()` serialization.
In `EccKeyPubP256::from_tomcrypt` (`utils/tsproto-types/src/crypto.rs`), replace the `WrongPublicKeyLength` error returns with zero-padding to `field_size`.
```rust
// Before (buggy):
let x_bytes = x.to_bytes_be();
let y_bytes = y.to_bytes_be();
if x_bytes.len() != field_size {
return Err(Error::WrongPublicKeyLength {
expected: field_size,
got: x_bytes.len(),
});
}
if y_bytes.len() != field_size {
return Err(Error::WrongPublicKeyLength {
expected: field_size,
got: y_bytes.len(),
});
}
// After (fixed):
let x_bytes = {
let raw = x.to_bytes_be();
let mut padded = vec![0u8; 32];
padded[32 - raw.len()..].copy_from_slice(&raw);
padded
let mut buf = vec![0u8; field_size.saturating_sub(x_bytes.len())];
buf.extend_from_slice(&x_bytes);
buf
};
let y_bytes = {
let raw = y.to_bytes_be();
let mut padded = vec![0u8; 32];
padded[32 - raw.len()..].copy_from_slice(&raw);
padded
let mut buf = vec![0u8; field_size.saturating_sub(y_bytes.len())];
buf.extend_from_slice(&y_bytes);
buf
};
```
@@ -49,17 +57,17 @@ fix: zero-pad P-256 ECDH coordinates to 32 bytes
#### What
Zero-pad P-256 public key coordinates (x, y) to exactly 32 bytes after `BigInt::to_bytes_be()` serialization.
In `EccKeyPubP256::from_tomcrypt`, replace `WrongPublicKeyLength` rejection of short P-256 coordinates with zero-padding to the field size.
#### Why
`BigInt::to_bytes_be()` strips leading zero bytes. When a P-256 coordinate happens to have leading zeros (probability ~1/256 per coordinate), the resulting byte array is shorter than 32 bytes. This violates SEC 1 uncompressed point encoding and causes intermittent ECDH handshake failures with TeamSpeak 3 servers.
`BigInt::to_bytes_be()` strips leading zero bytes. When a P-256 coordinate happens to have leading zeros (probability ~0.8% per coordinate), the ASN.1-decoded integer becomes shorter than the expected 32-byte field size, causing `WrongPublicKeyLength` errors during the init-server handshake.
#### Impact
- Fixes non-deterministic connection failures (~0.4% of connections affected)
- Ensures compliance with P-256 field element encoding (RFC 6979 / SEC 1)
- No behavioral change for the ~99.6% of connections where coordinates don't have leading zeros
- Fixes non-deterministic connection failures (~0.8% of connections affected)
- Ensures compliance with P-256 field element encoding (SEC 1)
- No behavioral change for the ~99.2% of connections where coordinates don't have leading zeros
#### Testing
@@ -70,3 +78,9 @@ Zero-pad P-256 public key coordinates (x, y) to exactly 32 bytes after `BigInt::
#### Notes
This fix is currently carried in the Chanora fork (`EdisonJwa/tsclientlib`). Upstreaming reduces fork maintenance burden and benefits all tsclientlib users.
---
## Status
**Ready for submission** — PR draft reviewed and verified against actual fork commit `8b7a322` (branch `fix/p256-short-coordinate-pad`). Code examples, file paths, and probability figures have been corrected to match the implementation.