Shares now record their field, so reconstruction returns the secret you split
2 hours ago
SecretSharingDotNet 1.1.0 fixes reconstruction quietly returning a different secret than the one you split. The fix is one more piece of data on each share: the field it was created in. Here that's level 17, written as hex 11. The release also closes a memory wipe gap on the older .NET targets.
Ask about this presentation
Chapters
Show transcriptHide transcript
SecretSharingDotNet 1.1.0 fixes reconstruction quietly returning a different secret than the one you split. The fix is one more piece of data on each share: the field it was created in. Here that's level 17, written as hex 11. The release also closes a memory wipe gap on the older .NET targets.
Until now, a share held only its index and its value. So reconstruction guessed the field: the smallest Mersenne prime above the largest value it saw. When every value in your subset fell below a smaller prime, it used the wrong field. In one test, a one-byte secret came back as 0x18 instead of 0xFF, from shares that were valid and untampered.
So 1.1.0 adds a SecurityLevel property to Share. MakeShares fills it with the exponent that actually governed the split, after any automatic raise, and reconstruction uses it. If your shares go from MakeShares to reconstruction without leaving memory, you change nothing. The round trip is simply correct now.
Stored shares are different. By default, ToCharArray still writes the two-part legacy form, so a share written out and read back loses its field. Pass ShareFormat.Extended, and a third segment carries the level in hex. The parser reads both forms, and older versions of the library refuse the extended one rather than misread it. It becomes the default in the next breaking-change cycle.
Shares you saved before this release carry no field. ReissueWithSecurityLevel copies them with the exponent attached, ready for the extended form. Or name the field on each call through the new reconstruction interface, and register it in your container, because the old registration doesn't cover it. Either way, pass the exponent the split really used. A one-byte secret split without an explicit level lands on 17.
Now the security fix. On netstandard2.0 and .NET Framework, the memory wipe used the marshalling size of a char, one byte instead of two, so it cleared only the front half of the buffer. A 10-character secret in a 16-element buffer kept its last two characters in plaintext. That buffer backs ConsolePasswordReader, ToPinnedSecure and every ToCharArray result. The modern targets were never affected.
Before you upgrade, check how you serialize, compare and subclass. Shares is no longer marked Serializable, which breaks one narrow case: a formatter surrogate registered for Share. Add one for Shares too, or persist through ToCharArray. The level now counts in equality, so a share without one doesn't equal the same coordinates with one. And the SecretReconstructor base finalizer is deprecated, and goes away in 2.0.0.
To upgrade, add version 1.1.0 of the package. If shares come from untrusted sources, two limits apply. The recorded level isn't authenticated, so your integrity check has to cover it too. And a short share string can name an exponent whose prime takes minutes to compute, so restrict exponents through your Mersenne prime provider. Store shares in the extended form, and reconstruction returns the secret you split.







