# publicly-derivable-encryption-secret

> A published digest determines the scalar of a registered curve point through resolved native calls.

Canonical: https://nightshade.dicksonwu.xyz/rules/publicly-derivable-encryption-secret.html
Release: Nightshade 0.1.1 (v0.1.1)

| Field | Value |
| --- | --- |
| Rule ID | `publicly-derivable-encryption-secret` |
| Severity | high |
| Confidence | varies |
| Maturity | experimental |
| Selection | Audit default |
| Policy intent | not required |
| Default enabled | yes |
| Category | Audit-default ordinary rules |
| Engine facts used | resolved-calls, private-provenance, public-sinks, direct-hash-inputs, exact-invocation-operands |
| Release | v0.1.1 |

## Selection and scope

Selected by the default audit profile, so an ordinary scan runs it.

```sh
./.nightshade/node_modules/.bin/nightshade ./contracts --detectors publicly-derivable-encryption-secret
./.nightshade/node_modules/.bin/nightshade detector show publicly-derivable-encryption-secret
```

The first command runs only this rule; `--detectors` takes a comma-separated list. The second prints the rule's metadata from your installed version.

Severity is review priority. It does not express exploitability or impact. Confidence is detector metadata, not a probability. All built-in rules are experimental.

Compiler scope: the engine supports the pinned profiles 0.28.0, 0.29.0, 0.30.0, 0.31.1, 0.33.0-rc.2, 0.34.0, 0.35.0-rc.1 and 0.35.0, with ZKIR2 by default. Support for this rule can be narrower; the rule documentation below states any narrower scope.

## Corpus checks

Synthetic corpus checks for this rule in the 0.1.1 proof run. A check counts only with compiler acceptance and complete analysis.

| Positive detected | Corrected quiet | Lookalike quiet | Other negative quiet | Incomplete |
| ---: | ---: | ---: | ---: | ---: |
| 1/1 | 1/1 | 1/1 | 0/0 | 0 |

No deviations were recorded for this rule.

These are behavior checks on synthetic fixtures, not a precision or recall estimate. See [evaluation](https://nightshade.dicksonwu.xyz/evaluation.md#synthetic-corpus).

## Rule documentation

From https://github.com/DicksonWu654/nightshade/blob/v0.1.1/docs/detectors/publicly-derivable-encryption-secret.md at v0.1.1.

Availability: default-on, **high severity / high confidence in the structural
relationship**. Select with `--detectors publicly-derivable-encryption-secret`.

### Description

A public digest can also determine the scalar used for a registered curve point.
If the application treats that point as an encryption key, review whether its
scalar was intended to remain private. The finding proves the modeled derivation
relationship; it does not establish encryption use or application intent.

### Example

An owned synthetic derivation:

```compact
pure circuit makePoint(seed: Bytes<32>): JubjubPoint {
  const digest = persistentHash<Vector<1, Bytes<32>>>([seed]);
  return ecMulGenerator(degradeToTransient(digest));
}
export circuit register(): [] {
  const seed = keyMaterial();
  accountId = disclose(persistentHash<Vector<1, Bytes<32>>>([seed]));
  registeredPoint = disclose(makePoint(seed));
}
```

The published digest supplies the same `degradeToTransient` input used in the
point derivation. Separating hash domains or using independent secret material
breaks this exact relationship.

### Scenario and evidence

The rule checks canonical resolved native calls, typed operands and straight-line
helper bodies, including immutable local aliases. Provider names, source notices,
commits and file fingerprints confer no role. The supported boundary is compiler
0.31.1, language 0.23.0 and ZKIR2 with its Field-based curve APIs. Different native profiles, unavailable
recipe proofs and exhausted applicability budgets produce rule-scoped incomplete
coverage when reached.

A finding also requires the same exact immutable raw witness operand, a public
`persistentHash<Vector<1, Bytes<32>>>` digest in an on-chain sink, an observed
successful derivation invocation, and its exact result as the last whole-root
`JubjubPoint` ledger write on one complete modeled outcome. Invocation arguments
and results are recorded separately. Provenance sets, declaration names, flow
strings and wildcard storage addresses never prove equality.

Last-write checking rejects overwritten registrations. Committed checkpoint
prefixes are separate outcomes. An impossible entire proof supplies no successful
prefix. The optional observations retain the baseline engine and original budgets;
missing invocation/digest evidence is explicitly incomplete.

### Recommendation

Separate public-identifier and private-key hash domains, or use independent
secret material. Confirm whether the registered point is a cryptographic key
before treating the structural finding as a vulnerability.

### Known false positives and limits

An intentionally public scalar or a curve point used for another purpose can
match. Encryption/ciphertext use, intended secrecy and exploitability are not
proven. Conditional/loop derivation bodies, arbitrary curve arithmetic, transformed
seeds, Map/struct registrations and cross-entry key lifecycles are outside this
proof boundary. Unknown reached recipe bodies are incomplete, not certified safe.
Independent witness invocations, different hash types/domains, discarded points,
exported-return-only digests and known constant-point derivations are quiet.

### Validation

Owned compiler-valid positive, domain-separated and independent-secret controls
exercise instruction/reference and cached/uncached evidence. Tests retain nested
and repeated calls, caller guards, state invalidation, checkpoint prefixes, exact
typed hash distinctions and explicit resource failures. These checks do not
establish independent application recall.

## Suppress a match

If a match is intentional, suppress it on the line before with the exact rule ID and a reason of at least eight characters:

```compact
// nightshade-disable-next-line publicly-derivable-encryption-secret -- Reason this match is intentional
```

Diagnostics cannot be suppressed, and an unmatched directive for a selected rule makes analysis incomplete. See [configuration](https://nightshade.dicksonwu.xyz/configuration.md#suppress-an-intentional-match) for fingerprint suppressions and baselines.

## References

- [Rule source document at v0.1.1](https://github.com/DicksonWu654/nightshade/blob/v0.1.1/docs/detectors/publicly-derivable-encryption-secret.md)
- [Catalog entry in rules.json](https://nightshade.dicksonwu.xyz/rules.json)
- [All rules](https://nightshade.dicksonwu.xyz/rules.md#audit-default-ordinary-rules)
- [Limitations](https://nightshade.dicksonwu.xyz/limitations.md)
