Skip to content

Conversation

@jhenahan
Copy link
Contributor

@jhenahan jhenahan commented Jan 3, 2025

Highlights:

  • Models input validation errors (pointer length and hex encoding)

  • Serde and rendering functions for PublicKey, SecretKey, and SignedMessage

  • Internals under Scoped

  • Uses constant-time Eq and Ord for SecretKey

  • For consistency, use Foreign.copyBytes everywhere that memcpy was once used

Comment on lines 198 to 228
-- | Signal your intent to encode secret key material for transmission
-- by wrapping a t'SecretKey' in t'UnsafeSecretKey'.
--
-- @since 0.0.3.0
newtype UnsafeSecretKey = UnsafeSecretKey SecretKey
deriving newtype
( Eq
-- ^ @since 0.0.3.0
-- Follows the t'SecretKey' instance.
)
deriving
( Display
-- ^ @since 0.0.3.0
-- Hexadecimal-encoded bytes.
)
via (ShowInstance UnsafeSecretKey)

-- | Hexadecimal-encoded bytes.
--
-- @since 0.0.3.0
instance Show UnsafeSecretKey where
show = ByteString.unpackChars . encodeSecretKeyHexByteString

-- | By lexicographical comparison of pointer contents.
--
-- ⚠️ Vulnerable to timing attacks!
--
-- @since 0.0.3.0
instance Ord UnsafeSecretKey where
a `compare` b =
foreignPtrOrd (coerce a) (coerce b) cryptoSignSecretKeyBytes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit over-engineered. encodeSecretKeyHexByteString ought to be a much simpler interface, no? I don't understand if there are invariants that are preserved by this type and its instances.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's intended as a guardrail to prevent you from doing things like serializing secret keys and using Ord in a way that's vulnerable to timing attacks without some kind of signal to readers that you're doing something that demands some extra attention.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do already have a (albeit low-tech) mechanism for signalling unsafe operations:
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to prefer sticking such things behind a gate that's very slightly higher than that since unsafe is a very overloaded word. To my mind, it implies there's some safeSecretKeyToHexByteString waiting to be discovered, and there just isn't. Disjoint concepts <=> disjoint types. I'm not married to it, though, and with constant-time Ord coming quite soon I could be convinced the power-to-weight isn't there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That option is available in the present API as unsafeSecretKeyHexByteString, which just wraps whatever SecretKey in the newtype first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed commits to strip that all out. Will update the API golden test once #171 lands and I rebase this PR on top of it.

@jhenahan jhenahan force-pushed the feat/new-signature-api branch 3 times, most recently from 6fb7ca6 to b19f0de Compare January 3, 2025 22:50
@jhenahan jhenahan force-pushed the feat/new-signature-api branch 4 times, most recently from f46f827 to 765c0de Compare January 3, 2025 23:19
Highlights:

- Models input validation errors (pointer length and hex encoding)

- Serde and rendering functions for `PublicKey`, `SecretKey`, and
  `SignedMessage`

- Internals under `Scoped`

- Uses constant-time `Eq` for `SecretKey`
For consistency, use `Foreign.copyBytes` everywhere that `memcpy` was once used.
@jhenahan jhenahan force-pushed the feat/new-signature-api branch from 765c0de to 0501798 Compare January 3, 2025 23:20
@jhenahan jhenahan force-pushed the feat/new-signature-api branch from 0501798 to 53c2a55 Compare January 3, 2025 23:23
@jhenahan jhenahan marked this pull request as draft January 6, 2025 00:53
@jhenahan jhenahan closed this Jan 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants