@atlasauth/pca-abe 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -4
- package/dist/abe.d.ts +83 -42
- package/dist/abe.js +290 -117
- package/dist/abe.js.map +1 -1
- package/dist/aead.js +1 -1
- package/dist/aead.js.map +1 -1
- package/dist/attributes.d.ts +28 -7
- package/dist/attributes.js +48 -27
- package/dist/attributes.js.map +1 -1
- package/dist/bls.d.ts +35 -12
- package/dist/bls.js +81 -11
- package/dist/bls.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/pca.d.ts +3 -2
- package/dist/pca.js.map +1 -1
- package/dist/policy.d.ts +7 -0
- package/dist/policy.js +21 -4
- package/dist/policy.js.map +1 -1
- package/dist/sss.d.ts +6 -0
- package/dist/sss.js +33 -19
- package/dist/sss.js.map +1 -1
- package/dist/wire.d.ts +0 -2
- package/dist/wire.js +0 -10
- package/dist/wire.js.map +1 -1
- package/package.json +3 -2
- package/dist/ibe.d.ts +0 -24
- package/dist/ibe.js +0 -71
- package/dist/ibe.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @atlasauth/pca-abe
|
|
2
2
|
|
|
3
|
-
Proof-carrying encryption for Proof-Carrying Authority (PCA). Tool payloads or results are sealed under an access policy over capability attributes (`holder:`, `verb:`, `resource:`, `scope:`), so they decrypt only for an agent whose PCA capability satisfies the policy. The construction is a
|
|
3
|
+
Proof-carrying encryption for Proof-Carrying Authority (PCA). Tool payloads or results are sealed under an access policy over capability attributes (`holder:`, `verb:`, `resource:`, `scope:`, and bound `act:` verb-on-resource pairs), so they decrypt only for an agent whose PCA capability satisfies the policy. The construction is Bethencourt-Sahai-Waters ciphertext-policy ABE (IEEE S&P 2007, ePrint 2006/309) with a per-key randomiser, adapted to the asymmetric (type-3) pairing on BLS12-381, over a monotone AND/OR/threshold tree shared by Shamir secret sharing, with the payload sealed by AES-256-GCM. Keys issued to different holders cannot be pooled to satisfy a policy neither satisfies.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -46,15 +46,30 @@ A key derived from a capability that does not satisfy the policy gets `{ ok: fal
|
|
|
46
46
|
|
|
47
47
|
## API
|
|
48
48
|
|
|
49
|
-
- Keys: `setup`, `keygenForAttributes`, `keygenForCapability
|
|
49
|
+
- Keys: `setup`, `keygenForAttributes`, `keygenForCapability`, `rerandomizeKey` (re-randomise a key, optionally to a subset of its attributes; needs only the public key).
|
|
50
50
|
- Raw bytes/text: `encryptForPolicy`, `decrypt`, `decryptText`, `parseCiphertext`.
|
|
51
51
|
- Tool payloads: `encryptToolPayload`, `decryptWithCapability`.
|
|
52
52
|
- Policies: `Policy` (`{ attr }`, `{ allOf }`, `{ anyOf }`, `{ threshold, of }`), `normalizePolicy`, `satisfies`, `policyAttributes`.
|
|
53
|
-
- Attributes: `Attr`, `capabilityAttributes`.
|
|
53
|
+
- Attributes: `Attr`, `capabilityAttributes`. A capability with ONE predicate yields flat `verb:`/`resource:` tokens plus `act:` pair tokens; a capability with TWO OR MORE predicates yields only `act:["verb","resource"]` pairs (plus `holder:`/`scope:`), so `read /public/*` + `write /acct/42` can never open a `read /acct/42` ciphertext (red-team RT-08; breaking: policies over flat tokens for multi-predicate capabilities must move to `Attr.act`). Predicate `where` conditions and other caveats are not encoded in any token. `scope:` tokens come only from the ROOT capability's caveats: a delegated hop's own `scope` caveats are restrictions, not grants (R2-07, breaking). For a delegated capability pass the chain, `capabilityAttributes(cap, { chain, principal })` / `keygenForCapability(msk, cap, [], { chain, principal })`; without a verified chain it gets no `scope:` tokens, and (R3-09, breaking) no `act:`/`verb:`/`resource:` tokens either, because the envelope is also read from the ROOT only (a delegatee-appended `envelope` caveat is a restriction and can no longer self-grant attributes); a chain that fails verification yields no attributes.
|
|
54
54
|
|
|
55
55
|
## Status
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
Research-grade, unaudited. Do not make it the only control for high-value data.
|
|
58
|
+
|
|
59
|
+
What holds, and under what assumptions:
|
|
60
|
+
|
|
61
|
+
- Collusion resistance. Every key carries a fresh randomiser `r`, so components of different keys do not combine; pooling two holders' keys (whole, or component by component) fails. This is tested, including against a py_ecc oracle for the key and ciphertext components and the pairing equations.
|
|
62
|
+
- The security notion of BSW07 is selective chosen-plaintext security (the adversary names the challenge policy before seeing the public key) in the generic bilinear group model, with the attribute hash as a random oracle. That proof is for the paper's symmetric pairing.
|
|
63
|
+
|
|
64
|
+
What is not established:
|
|
65
|
+
|
|
66
|
+
- The type-3 adaptation used here (which elements live in G1 and which in G2) is this package's own; it has no proof. No reduction to a standard assumption, no standard-model security.
|
|
67
|
+
- No adaptive security, and no CCA security of the ABE layer. AES-256-GCM over the whole header makes tampering detectable (integrity); that is not a CCA proof.
|
|
68
|
+
- The policy is public in the ciphertext (no attribute hiding). No key revocation. Whoever holds the master secret can decrypt everything. Policies are monotone (no negation).
|
|
69
|
+
- Not a zero-knowledge proof: confidentiality is bound to possession of capability-derived keys. Not post-quantum (pairing based). Not constant-time (JavaScript).
|
|
70
|
+
- Decryption costs one multi-pairing over the satisfied leaves; it is slower than the earlier per-attribute scheme.
|
|
71
|
+
|
|
72
|
+
Breaking change from earlier 0.x: key, public key, master key and ciphertext formats changed; old material is not readable.
|
|
58
73
|
|
|
59
74
|
Source and issues: https://github.com/Atlas-Authorization/pca
|
|
60
75
|
|
package/dist/abe.d.ts
CHANGED
|
@@ -1,64 +1,96 @@
|
|
|
1
1
|
import { type Capability } from '@atlasauth/pca';
|
|
2
|
+
import { type CapabilityAttributeOpts } from './attributes';
|
|
2
3
|
import { type Policy } from './policy';
|
|
3
4
|
/**
|
|
4
|
-
* Proof-carrying encryption: Ciphertext-Policy
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Proof-carrying encryption: Ciphertext-Policy Attribute-Based Encryption after Bethencourt, Sahai and
|
|
6
|
+
* Waters, "Ciphertext-Policy Attribute-Based Encryption" (IEEE S&P 2007, ePrint 2006/309; "BSW07"),
|
|
7
|
+
* Section 4, adapted to the asymmetric (type-3) pairing e: G1 x G2 -> GT of BLS12-381, with the payload
|
|
8
|
+
* sealed under AES-256-GCM. The access structure is the package's AND / OR / k-of-n tree, realised as a
|
|
9
|
+
* Shamir sharing down the tree exactly as BSW's access tree.
|
|
7
10
|
*
|
|
8
|
-
* CONSTRUCTION
|
|
9
|
-
* setup()
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
11
|
+
* CONSTRUCTION (g1, g2 the generators of G1, G2; H: {0,1}* -> G1 hash-to-curve, a random oracle)
|
|
12
|
+
* setup() alpha, beta <- Z_r*. MSK = (alpha, beta).
|
|
13
|
+
* MPK = ( h = beta*g2 in G2, f = beta^-1 * g1 in G1, Y = e(g1,g2)^alpha in GT ).
|
|
14
|
+
* keygen(S) r <- Z_r*; for each attribute j in S, r_j <- Z_r*.
|
|
15
|
+
* D = ((alpha + r)/beta) * g1 (G1)
|
|
16
|
+
* D_j = r*g1 + r_j*H(j) (G1), D'_j = r_j*g2 (G2) for j in S
|
|
17
|
+
* The per-USER randomiser r is shared by every component of one key and is what makes
|
|
18
|
+
* keys of different users incompatible (collusion resistance).
|
|
19
|
+
* encrypt(T, m) s <- Z_r*; C_0 = s*h (G2). Share s down the tree T (q_root(0) = s, Shamir per gate);
|
|
20
|
+
* for each leaf x with attribute j: C_x = q_x(0)*g2 (G2), C'_x = q_x(0)*H(j) (G1).
|
|
21
|
+
* The blinding value is K = Y^s = e(g1,g2)^(alpha*s); CEK = HKDF(K, salt).
|
|
22
|
+
* decrypt(SK, CT) DecryptNode at a leaf x (j in S):
|
|
23
|
+
* F_x = e(D_j, C_x) / e(C'_x, D'_j) = e(g1,g2)^(r*q_x(0)).
|
|
24
|
+
* At a gate, F_gate = prod_i F_i^{Delta_i(0)} over any t recovered children (Lagrange
|
|
25
|
+
* interpolation in the exponent) = e(g1,g2)^(r*q_gate(0)). At the root
|
|
26
|
+
* A = e(g1,g2)^(r*s), K = e(D, C_0) / A = e(g1,g2)^((alpha+r)*s - r*s) = Y^s.
|
|
19
27
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
28
|
+
* ADAPTATION TO TYPE-3 PAIRINGS (this is the package's adaptation, not a result of the BSW paper)
|
|
29
|
+
* BSW07 is stated in a symmetric bilinear group of composite-free prime order p with a single generator g.
|
|
30
|
+
* Here every element is assigned a fixed side so that each pairing in the scheme has one G1 and one G2
|
|
31
|
+
* argument: D, D_j, C'_x, f, H(.) in G1; h, D'_j, C_x, C_0 in G2. The one extra public element f = g^(1/beta)
|
|
32
|
+
* (present in BSW07's public key for Delegate) is used here for key re-randomisation and delegation
|
|
33
|
+
* (`rerandomizeKey`). The equations above are exactly BSW07's with g replaced by g1 or g2 according to the side.
|
|
26
34
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
35
|
+
* SECURITY NOTION (honest)
|
|
36
|
+
* BSW07 proves the scheme secure against collusion and chosen-plaintext attack in the SELECTIVE model
|
|
37
|
+
* (the adversary commits to the challenge access structure before seeing the public key), in the GENERIC
|
|
38
|
+
* BILINEAR GROUP model with H a random oracle (the paper's Theorem 1 is for the symmetric setting). This
|
|
39
|
+
* package does NOT carry that proof over: the type-3 adaptation above has no proof of its own here, the
|
|
40
|
+
* generic-group argument is not a reduction to a standard assumption, and no standard-model security is
|
|
41
|
+
* claimed. No adaptive (full) security, no CCA security of the ABE layer (the AES-GCM tag over the whole
|
|
42
|
+
* header makes tampering detectable, which is integrity, not a CCA proof), no key-revocation, no
|
|
43
|
+
* attribute hiding (the policy is public in the ciphertext), and the MSK holder can decrypt everything.
|
|
44
|
+
* Not a NIZK: confidentiality is bound to POSSESSION of capability-derived keys, not to a verified proof.
|
|
45
|
+
* Research-grade, not independently audited.
|
|
46
|
+
*
|
|
47
|
+
* What the construction does give, in the paper's model: two users whose attribute sets individually do
|
|
48
|
+
* not satisfy a policy cannot combine their keys (or components of them) to decrypt it, because every
|
|
49
|
+
* leaf recovery yields e(g1,g2)^(r*q) with the randomiser r of the key it was computed from, and the root
|
|
50
|
+
* needs a single consistent r.
|
|
34
51
|
*/
|
|
35
|
-
export declare const ABE_ALG = "
|
|
52
|
+
export declare const ABE_ALG = "bsw07-cpabe-bls12381-type3/lsss/aes-256-gcm";
|
|
36
53
|
export interface MasterPublicKey {
|
|
37
54
|
v: 1;
|
|
38
55
|
curve: 'bls12-381';
|
|
39
|
-
/** b64u compressed G2 point `
|
|
40
|
-
|
|
56
|
+
/** b64u compressed G2 point `h = beta * g2`. */
|
|
57
|
+
h: string;
|
|
58
|
+
/** b64u compressed G1 point `f = beta^-1 * g1` (used to re-randomise / delegate keys). */
|
|
59
|
+
f: string;
|
|
60
|
+
/** b64u 576-byte GT element `Y = e(g1, g2)^alpha`. */
|
|
61
|
+
egga: string;
|
|
41
62
|
}
|
|
42
63
|
export interface MasterSecretKey {
|
|
43
64
|
v: 1;
|
|
44
65
|
curve: 'bls12-381';
|
|
45
|
-
/** b64u 32-byte master
|
|
46
|
-
|
|
66
|
+
/** b64u 32-byte master scalar `alpha`. */
|
|
67
|
+
alpha: string;
|
|
68
|
+
/** b64u 32-byte master scalar `beta`. */
|
|
69
|
+
beta: string;
|
|
70
|
+
}
|
|
71
|
+
/** Per-attribute key component: `D_j = r*g1 + r_j*H(j)` (G1) and `D'_j = r_j*g2` (G2). */
|
|
72
|
+
export interface AttributeKey {
|
|
73
|
+
/** b64u compressed G1 point `D_j`. */
|
|
74
|
+
dj: string;
|
|
75
|
+
/** b64u compressed G2 point `D'_j`. */
|
|
76
|
+
dpj: string;
|
|
47
77
|
}
|
|
48
78
|
export interface DecryptionKey {
|
|
49
79
|
v: 1;
|
|
50
80
|
curve: 'bls12-381';
|
|
51
81
|
/** The capability's bound holder key, when issued from a capability (informational). */
|
|
52
82
|
holder?: string;
|
|
53
|
-
/**
|
|
54
|
-
|
|
83
|
+
/** b64u compressed G1 point `D = ((alpha + r)/beta) * g1`, bound to this key's randomiser `r`. */
|
|
84
|
+
d: string;
|
|
85
|
+
/** attribute token -> its `(D_j, D'_j)` components. */
|
|
86
|
+
attrs: Record<string, AttributeKey>;
|
|
55
87
|
}
|
|
56
|
-
/** The
|
|
88
|
+
/** The access tree: gates carry the Shamir threshold; leaves carry `C_x = q_x(0)*g2` and `C'_x = q_x(0)*H(attr)`. */
|
|
57
89
|
export type KemTree = {
|
|
58
90
|
kind: 'leaf';
|
|
59
91
|
attr: string;
|
|
60
|
-
|
|
61
|
-
|
|
92
|
+
c: string;
|
|
93
|
+
cp: string;
|
|
62
94
|
} | {
|
|
63
95
|
kind: 'gate';
|
|
64
96
|
t: number;
|
|
@@ -70,9 +102,11 @@ export type KemTree = {
|
|
|
70
102
|
export interface AbeCiphertext {
|
|
71
103
|
v: 1;
|
|
72
104
|
alg: typeof ABE_ALG;
|
|
73
|
-
/** b64u HKDF salt (16 bytes) bound into
|
|
105
|
+
/** b64u HKDF salt (16 bytes) bound into the CEK. */
|
|
74
106
|
salt: string;
|
|
75
|
-
/**
|
|
107
|
+
/** b64u compressed G2 point `C_0 = s * h`. */
|
|
108
|
+
c0: string;
|
|
109
|
+
/** The access tree (also the authenticated access structure). */
|
|
76
110
|
kem: KemTree;
|
|
77
111
|
/** b64u AES-256-GCM IV (12 bytes). */
|
|
78
112
|
iv: string;
|
|
@@ -97,7 +131,14 @@ export declare function keygenForAttributes(msk: MasterSecretKey, attrs: Iterabl
|
|
|
97
131
|
* extended with explicit extra tokens. The key can decrypt only ciphertexts whose policy is satisfied
|
|
98
132
|
* by this capability's authority.
|
|
99
133
|
*/
|
|
100
|
-
export declare function keygenForCapability(msk: MasterSecretKey, capability: Capability, extraAttributes?: Iterable<string
|
|
134
|
+
export declare function keygenForCapability(msk: MasterSecretKey, capability: Capability, extraAttributes?: Iterable<string>, opts?: CapabilityAttributeOpts): DecryptionKey;
|
|
135
|
+
/**
|
|
136
|
+
* Re-randomise a key with fresh randomness (BSW07 Delegate): the result decrypts exactly what `key` decrypts
|
|
137
|
+
* (restricted to `subset` when given, which must be attributes the key holds) but shares no component with it
|
|
138
|
+
* and carries a new randomiser `r + r~`, so it is as incompatible with the original as with any other user's key.
|
|
139
|
+
* Needs only the public key. Throws {@link PcaEncryptionError} on a malformed key / mpk or a subset attribute not held.
|
|
140
|
+
*/
|
|
141
|
+
export declare function rerandomizeKey(mpk: MasterPublicKey, key: DecryptionKey, subset?: Iterable<string>): DecryptionKey;
|
|
101
142
|
/**
|
|
102
143
|
* Encrypt `plaintext` so that it decrypts only for a holder whose attribute set satisfies `policy`.
|
|
103
144
|
* Throws {@link PcaEncryptionError} on an invalid policy or master public key.
|
|
@@ -109,8 +150,8 @@ export declare function encryptForPolicy(mpk: MasterPublicKey, policy: Policy, p
|
|
|
109
150
|
export declare function parseCiphertext(x: unknown): AbeCiphertext | null;
|
|
110
151
|
/**
|
|
111
152
|
* Decrypt. Returns the plaintext iff the key's attribute set satisfies the ciphertext's policy AND the
|
|
112
|
-
* AEAD authenticates; otherwise returns null (never throws).
|
|
113
|
-
*
|
|
153
|
+
* AEAD authenticates; otherwise returns null (never throws). Components of keys issued to different users
|
|
154
|
+
* carry different randomisers and cannot be combined.
|
|
114
155
|
*/
|
|
115
156
|
export declare function decrypt(key: DecryptionKey, ciphertext: unknown): Uint8Array | null;
|
|
116
157
|
/** Like {@link decrypt} but returns the plaintext decoded as UTF-8 text, or null. */
|