Skip to content

Commit f656039

Browse files
clean-up(trusted,getter calls): remove raw payload signature support (#2637)
Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com>
1 parent 677cb0b commit f656039

File tree

12 files changed

+232
-119
lines changed

12 files changed

+232
-119
lines changed

tee-worker/app-libs/stf/src/getter.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -169,35 +169,24 @@ impl TrustedGetterSigned {
169169

170170
pub fn verify_signature(&self) -> bool {
171171
// The signature should be valid in either case:
172-
// 1. payload
173-
// 2. blake2_256(payload)
174-
// 3. Signature Prefix + payload
175-
// 4. Signature Prefix + blake2_256payload
176-
//
177-
// @TODO P-639: Remove 1 and 3.
172+
// 1. blake2_256(payload)
173+
// 2. Signature Prefix + blake2_256payload
178174

179175
let payload = self.getter.encode();
180176
let hashed = blake2_256(&payload);
181177

182-
let prettified_msg_raw = self.getter.signature_message_prefix() + &hex_encode(&payload);
183-
let prettified_msg_raw = prettified_msg_raw.as_bytes();
184-
185178
let prettified_msg_hash = self.getter.signature_message_prefix() + &hex_encode(&hashed);
186179
let prettified_msg_hash = prettified_msg_hash.as_bytes();
187180

188181
// Most common signatures variants by clients are verified first (4 and 2).
189182
let is_valid = self.signature.verify(prettified_msg_hash, self.getter.sender_identity())
190-
|| self.signature.verify(&hashed, self.getter.sender_identity())
191-
|| self.signature.verify(&payload, self.getter.sender_identity())
192-
|| self.signature.verify(prettified_msg_raw, self.getter.sender_identity());
183+
|| self.signature.verify(&hashed, self.getter.sender_identity());
193184

194185
// in non-prod, we accept signature from Alice too
195186
if_development_or!(
196187
{
197188
is_valid
198-
|| self.signature.verify(&payload, &ALICE_ACCOUNTID32.into())
199189
|| self.signature.verify(&hashed, &ALICE_ACCOUNTID32.into())
200-
|| self.signature.verify(prettified_msg_raw, &ALICE_ACCOUNTID32.into())
201190
|| self.signature.verify(prettified_msg_hash, &ALICE_ACCOUNTID32.into())
202191
},
203192
{ is_valid }

tee-worker/app-libs/stf/src/trusted_call.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -330,26 +330,17 @@ impl TrustedCallVerification for TrustedCallSigned {
330330
payload.append(&mut shard.encode());
331331

332332
// The signature should be valid in either case:
333-
// 1. payload
334-
// 2. blake2_256(payload)
335-
// 3. Signature Prefix + payload
336-
// 4. Signature Prefix + blake2_256(payload)
337-
//
338-
// @TODO P-639: Remove 1 and 3.
333+
// 1. blake2_256(payload)
334+
// 2. Signature Prefix + blake2_256(payload)
339335

340336
let hashed = blake2_256(&payload);
341337

342-
let prettified_msg_raw = self.call.signature_message_prefix() + &hex_encode(&payload);
343-
let prettified_msg_raw = prettified_msg_raw.as_bytes();
344-
345338
let prettified_msg_hash = self.call.signature_message_prefix() + &hex_encode(&hashed);
346339
let prettified_msg_hash = prettified_msg_hash.as_bytes();
347340

348341
// Most common signatures variants by clients are verified first (4 and 2).
349342
self.signature.verify(prettified_msg_hash, self.call.sender_identity())
350343
|| self.signature.verify(&hashed, self.call.sender_identity())
351-
|| self.signature.verify(&payload, self.call.sender_identity())
352-
|| self.signature.verify(prettified_msg_raw, self.call.sender_identity())
353344
}
354345

355346
fn metric_name(&self) -> &'static str {

tee-worker/ts-tests/integration-tests/common/di-utils.ts

Lines changed: 81 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
import { ApiPromise } from '@polkadot/api';
2-
import { u8aToHex, hexToU8a, compactAddLength, bufferToU8a, u8aConcat, stringToU8a } from '@polkadot/util';
2+
import { u8aToHex, hexToU8a, compactAddLength, bufferToU8a, u8aConcat } from '@polkadot/util';
33
import { Codec } from '@polkadot/types/types';
44
import { TypeRegistry } from '@polkadot/types';
55
import { Bytes } from '@polkadot/types-codec';
66
import { IntegrationTestContext, JsonRpcRequest } from './common-types';
7-
import { WorkerRpcReturnValue, TrustedCallSigned, Getter, CorePrimitivesIdentity } from 'parachain-api';
8-
import { encryptWithTeeShieldingKey, Signer, encryptWithAes, sleep } from './utils';
7+
import type {
8+
WorkerRpcReturnValue,
9+
TrustedCallSigned,
10+
Getter,
11+
CorePrimitivesIdentity,
12+
TrustedGetterSigned,
13+
TrustedCall,
14+
} from 'parachain-api';
15+
import { encryptWithTeeShieldingKey, Signer, encryptWithAes, sleep, createLitentryMultiSignature } from './utils';
916
import { aesKey, decodeRpcBytesAsString, keyNonce } from './call';
1017
import { createPublicKey, KeyObject } from 'crypto';
1118
import WebSocketAsPromised from 'websocket-as-promised';
1219
import { H256, Index } from '@polkadot/types/interfaces';
13-
import { blake2AsHex, base58Encode } from '@polkadot/util-crypto';
14-
import { createJsonRpcRequest, nextRequestId } from './helpers';
20+
import { blake2AsHex, base58Encode, blake2AsU8a } from '@polkadot/util-crypto';
21+
import { createJsonRpcRequest, nextRequestId, stfErrorToString } from './helpers';
1522

1623
// Send the request to worker ws
1724
// we should perform different actions based on the returned status:
@@ -45,6 +52,9 @@ async function sendRequest(
4552

4653
if (res.status.isTrustedOperationStatus && res.status.asTrustedOperationStatus[0].isInvalid) {
4754
console.log('Rpc trusted operation execution failed, hash: ', res.value.toHex());
55+
const stfError = api.createType('StfError', res.value);
56+
const msg = stfErrorToString(stfError);
57+
console.log('TrustedOperationStatus error: ', msg);
4858
}
4959
// sending every response we receive from websocket
5060
if (onMessageReceived) onMessageReceived(res);
@@ -80,27 +90,37 @@ export const createSignedTrustedCall = async (
8090
mrenclave: string,
8191
nonce: Codec,
8292
params: any,
83-
withWrappedBytes = false
93+
withWrappedBytes = false,
94+
withPrefix = false
8495
): Promise<TrustedCallSigned> => {
8596
const [variant, argType] = trustedCall;
86-
const call = parachainApi.createType('TrustedCall', {
97+
const call: TrustedCall = parachainApi.createType('TrustedCall', {
8798
[variant]: parachainApi.createType(argType, params),
8899
});
89-
let payload = Uint8Array.from([
90-
...call.toU8a(),
91-
...nonce.toU8a(),
92-
...hexToU8a(mrenclave),
93-
...hexToU8a(mrenclave), // should be shard, but it's the same as MRENCLAVE in our case
94-
]);
100+
let payload: string = blake2AsHex(
101+
u8aConcat(
102+
call.toU8a(),
103+
nonce.toU8a(),
104+
hexToU8a(mrenclave),
105+
hexToU8a(mrenclave) // should be shard, but it's the same as MRENCLAVE in our case
106+
),
107+
256
108+
);
109+
95110
if (withWrappedBytes) {
96-
payload = u8aConcat(stringToU8a('<Bytes>'), payload, stringToU8a('</Bytes>'));
111+
payload = `<Bytes>${payload}</Bytes>`;
97112
}
98113

99-
// for bitcoin signature, we expect a hex-encoded `string` without `0x` prefix
100-
const signature = parachainApi.createType('LitentryMultiSignature', {
101-
[signer.type()]: u8aToHex(
102-
await signer.sign(signer.type() === 'bitcoin' ? u8aToHex(payload).substring(2) : payload)
103-
),
114+
if (withPrefix) {
115+
const prefix = getSignatureMessagePrefix(call);
116+
const msg = prefix + payload;
117+
payload = msg;
118+
console.log('Signing message: ', payload);
119+
}
120+
121+
const signature = await createLitentryMultiSignature(parachainApi, {
122+
signer,
123+
payload,
104124
});
105125

106126
return parachainApi.createType('TrustedCallSigned', {
@@ -110,34 +130,44 @@ export const createSignedTrustedCall = async (
110130
});
111131
};
112132

133+
// See TrustedCall.signature_message_prefix
134+
function getSignatureMessagePrefix(call: TrustedCall): string {
135+
if (call.isLinkIdentity) {
136+
return "By linking your identity to our platform, you're taking a step towards a more integrated experience. Please be assured, this process is safe and involves no transactions of your assets. Token: ";
137+
}
138+
139+
if (call.isRequestBatchVc) {
140+
const [, , assertions] = call.asRequestBatchVc;
141+
const length = assertions.length;
142+
143+
return `We are going to help you generate ${length} secure credential${
144+
length > 1 ? 's' : ''
145+
}. Please be assured, this process is safe and involves no transactions of your assets. Token: `;
146+
}
147+
148+
return 'Token: ';
149+
}
150+
113151
export const createSignedTrustedGetter = async (
114152
parachainApi: ApiPromise,
115153
trustedGetter: [string, string],
116154
signer: Signer,
117155
params: any
118-
) => {
156+
): Promise<TrustedGetterSigned> => {
119157
const [variant, argType] = trustedGetter;
120158
const getter = parachainApi.createType('TrustedGetter', {
121159
[variant]: parachainApi.createType(argType, params),
122160
});
123-
const payload = getter.toU8a();
161+
const payload = blake2AsU8a(getter.toU8a(), 256);
124162

125-
let signature;
126-
if (signer.type() === 'bitcoin') {
127-
const payloadStr = u8aToHex(payload).substring(2);
128-
129-
signature = parachainApi.createType('LitentryMultiSignature', {
130-
[signer.type()]: u8aToHex(await signer.sign(payloadStr)),
131-
});
132-
} else {
133-
signature = parachainApi.createType('LitentryMultiSignature', {
134-
[signer.type()]: u8aToHex(await signer.sign(payload)),
135-
});
136-
}
163+
let signature = await createLitentryMultiSignature(parachainApi, {
164+
signer,
165+
payload,
166+
});
137167

138168
return parachainApi.createType('TrustedGetterSigned', {
139-
getter: getter,
140-
signature: signature,
169+
getter,
170+
signature,
141171
});
142172
};
143173

@@ -160,7 +190,8 @@ export async function createSignedTrustedCallLinkIdentity(
160190
validationData: string,
161191
web3networks: string,
162192
aesKey: string,
163-
hash: string
193+
hash: string,
194+
options?: { withWrappedBytes?: boolean; withPrefix?: boolean }
164195
) {
165196
return createSignedTrustedCall(
166197
parachainApi,
@@ -171,7 +202,9 @@ export async function createSignedTrustedCallLinkIdentity(
171202
signer,
172203
mrenclave,
173204
nonce,
174-
[primeIdentity.toHuman(), primeIdentity.toHuman(), identity, validationData, web3networks, aesKey, hash]
205+
[primeIdentity.toHuman(), primeIdentity.toHuman(), identity, validationData, web3networks, aesKey, hash],
206+
options?.withWrappedBytes,
207+
options?.withPrefix
175208
);
176209
}
177210

@@ -207,15 +240,18 @@ export async function createSignedTrustedCallRequestVc(
207240
primeIdentity: CorePrimitivesIdentity,
208241
assertion: string,
209242
aesKey: string,
210-
hash: string
243+
hash: string,
244+
options?: { withWrappedBytes?: boolean; withPrefix?: boolean }
211245
) {
212246
return await createSignedTrustedCall(
213247
parachainApi,
214248
['request_vc', '(LitentryIdentity, LitentryIdentity, Assertion, Option<RequestAesKey>, H256)'],
215249
signer,
216250
mrenclave,
217251
nonce,
218-
[primeIdentity.toHuman(), primeIdentity.toHuman(), assertion, aesKey, hash]
252+
[primeIdentity.toHuman(), primeIdentity.toHuman(), assertion, aesKey, hash],
253+
options?.withWrappedBytes,
254+
options?.withPrefix
219255
);
220256
}
221257

@@ -227,7 +263,8 @@ export async function createSignedTrustedCallRequestBatchVc(
227263
primeIdentity: CorePrimitivesIdentity,
228264
assertion: string,
229265
aesKey: string,
230-
hash: string
266+
hash: string,
267+
options?: { withWrappedBytes?: boolean; withPrefix?: boolean }
231268
) {
232269
return await createSignedTrustedCall(
233270
parachainApi,
@@ -238,7 +275,9 @@ export async function createSignedTrustedCallRequestBatchVc(
238275
signer,
239276
mrenclave,
240277
nonce,
241-
[primeIdentity.toHuman(), primeIdentity.toHuman(), assertion, aesKey, hash]
278+
[primeIdentity.toHuman(), primeIdentity.toHuman(), assertion, aesKey, hash],
279+
options?.withWrappedBytes,
280+
options?.withPrefix
242281
);
243282
}
244283

@@ -340,8 +379,7 @@ export const sendRequestFromTrustedCall = async (
340379
) => {
341380
// construct trusted operation
342381
const trustedOperation = context.api.createType('TrustedOperation', { direct_call: call });
343-
console.log('top: ', trustedOperation.toJSON());
344-
console.log('top hash', blake2AsHex(trustedOperation.toU8a()));
382+
console.log('trustedOperation: ', JSON.stringify(trustedOperation.toHuman(), null, 2));
345383
// create the request parameter
346384
const requestParam = await createAesRequest(
347385
context.api,

tee-worker/ts-tests/integration-tests/common/helpers.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import * as ecc from 'tiny-secp256k1';
1111
import { ethers, Wallet } from 'ethers';
1212
import { EthersSigner, PolkadotSigner, BitcoinSigner } from './utils/crypto';
1313
import { Wallets } from './common-types';
14+
import type { ErrorDetail, StfError } from 'parachain-api';
15+
1416
export function blake2128Concat(data: HexString | Uint8Array): Uint8Array {
1517
return u8aConcat(blake2AsU8a(data, 128), u8aToU8a(data));
1618
}
@@ -73,3 +75,33 @@ export const createWeb3Wallets = (): Wallets => {
7375

7476
return wallets;
7577
};
78+
79+
export function stfErrorToString(stfError: StfError): string {
80+
if (stfError.isRequestVCFailed) {
81+
const [_assertionIgnored, errorDetail] = stfError.asRequestVCFailed;
82+
83+
return `${stfError.type}: ${errorDetail.type}: ${errorDetail.value?.toHuman()}`;
84+
}
85+
86+
if (
87+
stfError.isActivateIdentityFailed ||
88+
stfError.isDeactivateIdentityFailed ||
89+
stfError.isSetIdentityNetworksFailed ||
90+
stfError.isLinkIdentityFailed ||
91+
stfError.isMissingPrivileges ||
92+
stfError.isRemoveIdentityFailed ||
93+
stfError.isDispatch
94+
) {
95+
const errorDetail = stfError.value as ErrorDetail;
96+
97+
return `${stfError.type}: ${errorDetail.type}: ${errorDetail.value?.toHuman()}`;
98+
}
99+
100+
if (stfError.isInvalidNonce) {
101+
const [nonce1, nonce2] = stfError.asInvalidNonce;
102+
103+
return `${stfError.type}: [${nonce1?.toHuman()}, ${nonce2?.toHuman()}]`;
104+
}
105+
106+
return stfError.type;
107+
}

0 commit comments

Comments
 (0)