Skip to content

Commit

Permalink
apply pr suggestions for #273
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Sep 4, 2023
1 parent 281e19e commit f1f729b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 117 deletions.
70 changes: 15 additions & 55 deletions src/characters/cbd-recipient.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import {
AccessControlPolicy,
AuthenticatedData,
Ciphertext,
combineDecryptionSharesSimple,
Context,
DecryptionShareSimple,
decryptWithSharedSecret,
EncryptedThresholdDecryptionRequest,
EncryptedThresholdDecryptionResponse,
FerveoVariant,
SessionSharedSecret,
SessionStaticSecret,
ThresholdDecryptionRequest,
ThresholdMessageKit,
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import { keccak256 } from 'ethers/lib/utils';

import { DkgCoordinatorAgent, DkgParticipant } from '../agents/coordinator';
import { ConditionExpression } from '../conditions';
import { DkgClient, DkgRitual } from '../dkg';
import { DkgRitual } from '../dkg';
import { PorterClient } from '../porter';
import { fromJSON, toBytes, toJSON } from '../utils';
import { fromJSON, objectEquals, toJSON } from '../utils';

export type ThresholdDecrypterJSON = {
porterUri: string;
Expand All @@ -46,55 +42,23 @@ export class ThresholdDecrypter {
// Retrieve and decrypt ciphertext using provider and condition expression
public async retrieveAndDecrypt(
provider: ethers.providers.Provider,
signer: ethers.Signer,
conditionExpr: ConditionExpression,
ciphertext: Ciphertext
thresholdMessageKit: ThresholdMessageKit
): Promise<Uint8Array> {
const acp = await this.makeAcp(provider, signer, conditionExpr, ciphertext);

const decryptionShares = await this.retrieve(
provider,
conditionExpr,
ciphertext,
acp,
signer
thresholdMessageKit
);

const sharedSecret = combineDecryptionSharesSimple(decryptionShares);
return decryptWithSharedSecret(
ciphertext,
conditionExpr.asAad(),
sharedSecret
);
}

private async makeAcp(
provider: ethers.providers.Provider,
signer: ethers.Signer,
conditionExpr: ConditionExpression,
ciphertext: Ciphertext
) {
const dkgRitual = await DkgClient.getExistingRitual(
provider,
this.ritualId
);
const authData = new AuthenticatedData(
dkgRitual.dkgPublicKey,
conditionExpr.toWASMConditions()
);

const headerHash = keccak256(ciphertext.header.toBytes());
const authorization = await signer.signMessage(headerHash);

return new AccessControlPolicy(authData, toBytes(authorization));
return thresholdMessageKit.decryptWithSharedSecret(sharedSecret);
}

// Retrieve decryption shares
public async retrieve(
provider: ethers.providers.Provider,
conditionExpr: ConditionExpression,
ciphertext: Ciphertext,
acp: AccessControlPolicy,
thresholdMessageKit: ThresholdMessageKit,
signer?: ethers.Signer
): Promise<DecryptionShareSimple[]> {
const dkgParticipants = await DkgCoordinatorAgent.getParticipants(
Expand All @@ -106,10 +70,9 @@ export class ThresholdDecrypter {
.toJson();
const { sharedSecrets, encryptedRequests } = this.makeDecryptionRequests(
this.ritualId,
ciphertext,
contextStr,
new Context(contextStr),
dkgParticipants,
acp
thresholdMessageKit
);

const { encryptedResponses, errors } = await this.porter.cbdDecrypt(
Expand Down Expand Up @@ -154,20 +117,19 @@ export class ThresholdDecrypter {

private makeDecryptionRequests(
ritualId: number,
ciphertext: Ciphertext,
contextStr: string,
conditionContext: Context,
dkgParticipants: Array<DkgParticipant>,
acp: AccessControlPolicy
thresholdMessageKit: ThresholdMessageKit
): {
sharedSecrets: Record<string, SessionSharedSecret>;
encryptedRequests: Record<string, EncryptedThresholdDecryptionRequest>;
} {
const decryptionRequest = new ThresholdDecryptionRequest(
ritualId,
FerveoVariant.simple,
ciphertext.header,
acp,
new Context(contextStr)
thresholdMessageKit.ciphertextHeader,
thresholdMessageKit.acp,
conditionContext
);

const ephemeralSessionKey = this.makeSessionKey();
Expand Down Expand Up @@ -234,8 +196,6 @@ export class ThresholdDecrypter {
}

public equals(other: ThresholdDecrypter): boolean {
return (
this.porter.porterUrl.toString() === other.porter.porterUrl.toString()
);
return objectEquals(this.toObj(), other.toObj());
}
}
33 changes: 21 additions & 12 deletions src/characters/enrico.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {
Ciphertext,
AccessControlPolicy,
DkgPublicKey,
ferveoEncrypt,
encryptForDkg,
MessageKit,
PublicKey,
SecretKey,
ThresholdMessageKit,
} from '@nucypher/nucypher-core';
import { arrayify, keccak256 } from 'ethers/lib/utils';

import { ConditionExpression } from '../conditions';
import { Keyring } from '../keyring';
Expand Down Expand Up @@ -51,26 +53,33 @@ export class Enrico {

public encryptMessageCbd(
plaintext: Uint8Array | string,
withConditions?: ConditionExpression
): { ciphertext: Ciphertext; aad: Uint8Array } {
if (!withConditions) {
withConditions = this.conditions;
conditions?: ConditionExpression
): ThresholdMessageKit {
if (!conditions) {
conditions = this.conditions;
}

if (!withConditions) {
if (!conditions) {
throw new Error('Conditions are required for CBD encryption.');
}

if (!(this.encryptingKey instanceof DkgPublicKey)) {
throw new Error('Wrong key type. Use encryptMessagePre instead.');
}

const aad = withConditions.asAad();
const ciphertext = ferveoEncrypt(
const [ciphertext, authenticatedData] = encryptForDkg(
plaintext instanceof Uint8Array ? plaintext : toBytes(plaintext),
aad,
this.encryptingKey
this.encryptingKey,
conditions.toWASMConditions()
);

const headerHash = keccak256(ciphertext.header.toBytes());
const authorization = this.keyring.signer.sign(arrayify(headerHash));
const acp = new AccessControlPolicy(
authenticatedData,
authorization.toBEBytes()
);
return { ciphertext, aad };

return new ThresholdMessageKit(ciphertext, acp);
}
}
2 changes: 1 addition & 1 deletion test/integration/dkg-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('DkgCoordinatorAgent', () => {

it('fetches participants from the coordinator', async () => {
const provider = fakeProvider(SecretKey.random().toBEBytes());
const fakeParticipants = fakeDkgParticipants(fakeRitualId);
const fakeParticipants = await fakeDkgParticipants(fakeRitualId);
const getParticipantsSpy = mockGetParticipants(
fakeParticipants.participants
);
Expand Down
21 changes: 9 additions & 12 deletions test/unit/cbd-strategy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
fakeDkgParticipants,
fakeDkgRitual,
fakeProvider,
fakeSigner,
fakeTDecFlow,
fakeUrsulas,
makeCohort,
Expand All @@ -30,7 +29,6 @@ const {

// Shared test variables
const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
const aliceSigner = fakeSigner(aliceSecretKey.toBEBytes());
const aliceProvider = fakeProvider(aliceSecretKey.toBEBytes());
const ownsNFT = new ERC721Ownership({
contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
Expand All @@ -41,6 +39,7 @@ const conditionExpr = new ConditionExpression(ownsNFT);
const ursulas = fakeUrsulas();
const variant = FerveoVariant.precomputed;
const ritualId = 0;
const web3Provider = fakeProvider(aliceSecretKey.toBEBytes());

const makeCbdStrategy = async () => {
const cohort = await makeCohort(ursulas);
Expand All @@ -54,7 +53,6 @@ async function makeDeployedCbdStrategy() {

const mockedDkg = fakeDkgFlow(variant, 0, 4, 4);
const mockedDkgRitual = fakeDkgRitual(mockedDkg);
const web3Provider = fakeProvider(aliceSecretKey.toBEBytes());
const getUrsulasSpy = mockGetUrsulas(ursulas);
const getExistingRitualSpy = mockGetExistingRitual(mockedDkgRitual);
const deployedStrategy = await strategy.deploy(web3Provider, ritualId);
Expand Down Expand Up @@ -104,20 +102,20 @@ describe('CbdDeployedStrategy', () => {
const { mockedDkg, deployedStrategy } = await makeDeployedCbdStrategy();

const message = 'this is a secret';
const { ciphertext, aad } = deployedStrategy
const thresholdMessageKit = deployedStrategy
.makeEncrypter(conditionExpr)
.encryptMessageCbd(message);

// Setup mocks for `retrieveAndDecrypt`
const { decryptionShares } = fakeTDecFlow({
const { decryptionShares } = await fakeTDecFlow({
...mockedDkg,
message: toBytes(message),
aad,
ciphertext,
conditionExpr,
dkgPublicKey: mockedDkg.dkg.publicKey(),
thresholdMessageKit,
});
const { participantSecrets, participants } = fakeDkgParticipants(
mockedDkg.ritualId,
variant
const { participantSecrets, participants } = await fakeDkgParticipants(
mockedDkg.ritualId
);
const requesterSessionKey = SessionStaticSecret.random();
const decryptSpy = mockCbdDecrypt(
Expand All @@ -133,9 +131,8 @@ describe('CbdDeployedStrategy', () => {
const decryptedMessage =
await deployedStrategy.decrypter.retrieveAndDecrypt(
aliceProvider,
aliceSigner,
conditionExpr,
ciphertext
thresholdMessageKit
);
expect(getUrsulasSpy).toHaveBeenCalled();
expect(getParticipantsSpy).toHaveBeenCalled();
Expand Down
Loading

0 comments on commit f1f729b

Please sign in to comment.