Skip to content

Commit

Permalink
Merge pull request #11 from tide-foundation/staging
Browse files Browse the repository at this point in the history
3.1 into main
  • Loading branch information
sundayScoop authored Apr 27, 2023
2 parents ac29e54 + ab94fae commit 83edffb
Show file tree
Hide file tree
Showing 17 changed files with 148 additions and 286 deletions.
21 changes: 2 additions & 19 deletions H4x2-Node/H4x2-Node/Controllers/CreateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,31 +63,14 @@ public async Task<IActionResult> GenShard([FromQuery] string uid, int numKeys, I
}

[HttpPost]
public IActionResult SendShard([FromQuery] string uid, string[] yijCipher, string[] gKnCipher, string[] gMultipliers)
public IActionResult SendShard([FromQuery] string uid, string[] yijCipher, string[] gMultipliers, Point R2)
{
try
{
if (uid == null) throw new ArgumentNullException("uid cannot be null");
string[][] gKnCiphers = gKnCipher.Select(c => c.Split(",")).ToArray(); // when we need to pass double array - consider cleaning up in future

Point[] gMultiplier = Utils.GetPointList(gMultipliers);
var response = _keyGenerator.SendShard(uid, gKnCiphers, yijCipher, gMultiplier);
return Ok(response);
}catch(Exception ex){
return Ok("--FAILED--:" + ex.Message);
}
}

[HttpPost]
public IActionResult SetKey([FromQuery] string uid, string[] gKntesti, Point R2, string[] ephKeyj)
{
try
{
if (uid == null) throw new ArgumentNullException("uid cannot be null");

Point[] gKntesti_P = Utils.GetPointList(gKntesti).ToArray();

var response = _keyGenerator.SetKey(uid, gKntesti_P, R2, ephKeyj);
var response = _keyGenerator.SendShard(uid, yijCipher, gMultiplier, R2);
return Ok(response);
}catch(Exception ex){
return Ok("--FAILED--:" + ex.Message);
Expand Down
2 changes: 1 addition & 1 deletion H4x2-Node/H4x2-Node/H4x2-Node.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="LazyCache" Version="2.4.0" />
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
<PackageReference Include="H4x2-TinySDK" Version="0.1.10" />
<PackageReference Include="H4x2-TinySDK" Version="0.1.11" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion H4x2-Node/H4x2-Node/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

var builder = WebApplication.CreateBuilder(args);

var version = "H4x2-ORK:3.0";
var version = "H4x2-ORK:3.1";
var isThrottled = true;
var key = new Key(BigInteger.Parse(args.Length == 0 ? Environment.GetEnvironmentVariable("TIDE_KEY") : args[0]));
var threshold = 3;
Expand Down
2 changes: 1 addition & 1 deletion H4x2-Node/H4x2-Node/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
"Api": "https://new-simulator.australiaeast.cloudapp.azure.com"
}
}
}
}
8 changes: 4 additions & 4 deletions H4x2-Node/H4x2-Node/wwwroot/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ import { SignIn, SimulatorFlow, SignUp, Point } from "../modules/H4x2-TideJS/ind
$('#loader').show();
var config = {
simulatorUrl: 'https://new-simulator.australiaeast.cloudapp.azure.com/',
vendorUrl: 'https://h4x-staging-vendor.azurewebsites.net/'
vendorUrl: 'https://h4x22vendor.azurewebsites.net/'
}
var signin = new SignIn(config);
var signinResponse = signin.start_Heimdall(user, pass);
Expand All @@ -184,7 +184,7 @@ import { SignIn, SimulatorFlow, SignUp, Point } from "../modules/H4x2-TideJS/ind
$('#loader').show();
var config = {
simulatorUrl: 'https://new-simulator.australiaeast.cloudapp.azure.com/',
vendorUrl: 'https://h4x-staging-vendor.azurewebsites.net/'
vendorUrl: 'https://h4x22vendor.azurewebsites.net/'
}
var signin = new SignIn(config);
var signinResponse = signin.start(user, pass);
Expand Down Expand Up @@ -216,7 +216,7 @@ import { SignIn, SimulatorFlow, SignUp, Point } from "../modules/H4x2-TideJS/ind
var config = {
orkInfo: orkUrls.sort((a, b) => a[0].localeCompare(b[0])), //Sorting orklist based on ork Id,
simulatorUrl: 'https://new-simulator.australiaeast.cloudapp.azure.com/',
vendorUrl: 'https://h4x-staging-vendor.azurewebsites.net/'
vendorUrl: 'https://h4x22vendor.azurewebsites.net/'
}

var signup = new SignUp(config);
Expand Down Expand Up @@ -248,7 +248,7 @@ import { SignIn, SimulatorFlow, SignUp, Point } from "../modules/H4x2-TideJS/ind
var config = {
orkInfo: orkUrls.sort((a, b) => a[0].localeCompare(b[0])), //Sorting orklist based on ork Id,
simulatorUrl: 'https://new-simulator.australiaeast.cloudapp.azure.com/',
vendorUrl: 'https://h4x-staging-vendor.azurewebsites.net/'
vendorUrl: 'https://h4x22vendor.azurewebsites.net/'
}

var signup = new SignUp(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import Point from "../Ed25519/point.js"
import GenShardResponse from "../Models/GenShardResponse.js";
import SetKeyResponse from "../Models/SetKeyResponse.js";
import ClientBase from "./ClientBase.js"
import SendShardResponse from "../Models/SendShardResponse.js";

Expand Down Expand Up @@ -79,14 +78,14 @@ export default class NodeClient extends ClientBase {
/**
* @param {string} uid
* @param {string[]} shares
* @param {string[][]} gKnCiphers
* @param {Point} R2
* @param {Point[]} gMultipliers
*/
async SendShard(uid, shares, gKnCiphers, gMultipliers) {
async SendShard(uid, shares, R2, gMultipliers) {
const data = this._createFormData(
{
'yijCipher': shares,
'gKnCipher': gKnCiphers,
'R2': R2.toBase64(),
'gMultipliers': gMultipliers.map(p => p == null ? "" : p.toBase64())
});
const response = await this._post(`/Create/SendShard?uid=${uid}`, data);
Expand All @@ -95,25 +94,6 @@ export default class NodeClient extends ClientBase {
return SendShardResponse.from(responseData);
}

/**
* @param {string} uid
* @param {Point[]} gKntest
* @param {Point} R2
* @param {string[]} ephKeyj
*/
async SetKey(uid, gKntest, R2, ephKeyj) {
const data = this._createFormData(
{
'gKntesti': gKntest.map(gKtest => gKtest.toBase64()),
'R2': R2.toBase64(),
'ephKeyj': ephKeyj
}
);
const response = await this._post(`/Create/SetKey?uid=${uid}`, data);
const responseData = await this._handleError(response, "SetKey");
return SetKeyResponse.from(responseData)
}


/**
* @param {string} uid
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import NodeClient from "../Clients/NodeClient.js";
import Point from "../Ed25519/point.js";
import { Commit_DecryptCVK, GenShardReply, SendShardReply, SetKeyValidation } from "../Math/KeyGeneration.js";
import SetKeyResponse from "../Models/SetKeyResponse.js";
import { Commit_DecryptCVK, GenShardReply, SendShardReply } from "../Math/KeyGeneration.js";

export default class dKeyGenerationFlow {
/**
Expand Down Expand Up @@ -31,34 +30,17 @@ export default class dKeyGenerationFlow {
/**
* @param {string} uid
* @param {string[][]} YijCipher
* @param {string[][]} gKnCipher
* @param {Point} R2
* @param {Point[]} gMultipliers
*/
async SendShard(uid, YijCipher, gKnCipher, gMultipliers) {
const clients = this.orks.map(ork => new NodeClient(ork[1])) // create node clients

const pre_SendShardResponses = clients.map((client, i) => client.SendShard(uid, YijCipher[i], gKnCipher, gMultipliers))
const SendShardResponses = await Promise.all(pre_SendShardResponses);

return SendShardReply(SendShardResponses, this.orks.map(ork => ork[0]), gKnCipher);
}

/**
* @param {string} uid
* @param {Point[]} gKntest
* @param {Point[]} gKn
* @param {Point} R2
* @param {bigint} timestamp
* @param {Point[]} mgORKi
* @param {string[]} ephKeyj
*/
async SetKey(uid, gKntest, gKn, R2, timestamp, mgORKi, ephKeyj) {
async SendShard(uid, YijCipher, R2, gMultipliers, timestamp) {
const clients = this.orks.map(ork => new NodeClient(ork[1])) // create node clients

const pre_setKeyResponses = clients.map((client, i) => client.SetKey(uid, gKntest, R2, ephKeyj));
const SetKeyResponses = await Promise.all(pre_setKeyResponses);
const pre_SendShardResponses = clients.map((client, i) => client.SendShard(uid, YijCipher[i], R2, gMultipliers))
const SendShardResponses = await Promise.all(pre_SendShardResponses);

return await SetKeyValidation(SetKeyResponses, uid, gKn, gKntest, timestamp, mgORKi, R2);
return SendShardReply(uid, SendShardResponses, this.orks.map(ork => ork[2]), timestamp, R2);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,15 @@ export default class SignUp {

// Start Key Generation Flow
const KeyGenFlow = new dKeyGenerationFlow(this.orkInfo);
const {sortedShares, timestamp, gKCiphers} = await KeyGenFlow.GenShard(uid, 2); // GenShard
const {gKntest, R2, gMultiplied, gKn, ephKeys} = await KeyGenFlow.SendShard(uid, sortedShares, gKCiphers, [null, passwordPoint_R]);
const {sortedShares, timestamp, R2} = await KeyGenFlow.GenShard(uid, 2); // GenShard
const {S, encCommitStatei, gMultiplied} = await KeyGenFlow.SendShard(uid, sortedShares, R2, [null, passwordPoint_R], timestamp);

// Do Prism Flow
const prismFlow = new PrismFlow(this.orkInfo);
const gPRISMAuth = await prismFlow.GetGPrismAuth(gMultiplied[1], random); // there are some redundant calcs by calling these functions serpately
const prismAuthi = await prismFlow.GetPrismAuths(gMultiplied[1], random); // but later on, we'll only need one or the other, so i'm keeping them seperate

// Resume Key Generation Flow
const {S, encCommitStatei} = await KeyGenFlow.SetKey(uid, gKntest, gKn, R2, timestamp, this.orkInfo.map(ork => ork[2]), ephKeys);
const CVK = await KeyGenFlow.Commit(uid, S, encCommitStatei, prismAuthi, gPRISMAuth)
const encryptedCode = await encryptData(secretCode, BigIntToByteArray(CVK));

Expand All @@ -105,16 +104,15 @@ export default class SignUp {

// Start Key Generation Flow
const KeyGenFlow = new dKeyGenerationFlow(this.orkInfo);
const {sortedShares, timestamp, gKCiphers} = await KeyGenFlow.GenShard(uid, 2); // GenShard
const {gKntest, R2, gMultiplied, gKn, ephKeys} = await KeyGenFlow.SendShard(uid, sortedShares, gKCiphers, [null, passwordPoint_R]);
const {sortedShares, timestamp, R2} = await KeyGenFlow.GenShard(uid, 2); // GenShard
const {S, encCommitStatei, gMultiplied} = await KeyGenFlow.SendShard(uid, sortedShares, R2, [null, passwordPoint_R], timestamp);

// Do Prism Flow
const prismFlow = new PrismFlow(this.orkInfo);
const gPRISMAuth = await prismFlow.GetGPrismAuth(gMultiplied[1], random); // there are some redundant calcs by calling these functions serpately
const prismAuthi = await prismFlow.GetPrismAuths(gMultiplied[1], random); // but later on, we'll only need one or the other, so i'm keeping them seperate

// Resume Key Generation Flow
const {S, encCommitStatei} = await KeyGenFlow.SetKey(uid, gKntest, gKn, R2, timestamp, this.orkInfo.map(ork => ork[2]), ephKeys);
const CVK = await KeyGenFlow.Commit(uid, S, encCommitStatei, prismAuthi, gPRISMAuth)

return {CVK: CVK, UID: uid}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Point from "../Ed25519/point.js";
import GenShardResponse from "../Models/GenShardResponse.js";
import SendShardResponse from "../Models/SendShardResponse.js";
import SetKeyResponse from "../Models/SetKeyResponse.js";
import { createAESKey, decryptData, encryptData } from "../Tools/AES.js";
import { SHA256_Digest, SHA512_Digest } from "../Tools/Hash.js";
import { BigIntFromByteArray, BigIntToByteArray, bytesToBase64, ConcatUint8Arrays, median, mod, StringToUint8Array } from "../Tools/Utils.js";
Expand All @@ -12,80 +11,41 @@ import { GetLi } from "./SecretShare.js";
*/
export function GenShardReply(genShardResponses){
const sortedShares = SortShares(genShardResponses.map(resp => resp.YijCiphers)); // sort shares so they can easily be sent to respective orks
const gKCiphers = genShardResponses.map(resp => resp.GKnCipher); // we need to send all gKCiphers to every ork
const timestamp = median(genShardResponses.map(resp => resp.Timestampi));
return {sortedShares: sortedShares, timestamp: timestamp, gKCiphers: gKCiphers};
const R2 = genShardResponses.reduce((sum, next) => next.GRi.add(sum), Point.infinity);
return {sortedShares: sortedShares, timestamp: timestamp, R2: R2};
}

/**
* @param {string} keyId
* @param {SendShardResponse[]} sendShardResponses
* @param {string[]} orkIds
* @param {string[][]} gKCiphers
*/
export async function SendShardReply(sendShardResponses, orkIds, gKCiphers){
// Assert all ork returned same number of responses
const equalLengthCheck = sendShardResponses.every(resp => resp.gKtesti.length == sendShardResponses[0].gKtesti.length && resp.gMultiplied.length == sendShardResponses[0].gMultiplied.length);
if(!equalLengthCheck) throw new Error("SendShardReply: An ORK returned a different number of points that others");
const cipherLengthCheck = gKCiphers.every(cipher => cipher.length == gKCiphers[0].length);
if(!cipherLengthCheck) throw new Error("SendShardReply: ORKs returned different number of ciphers")

// Decrypts the partial publics
const pre_ephKeys = sendShardResponses.map(async resp => await createAESKey(BigIntToByteArray(BigInt(resp.ephKeyi)), ["decrypt"]));
const ephKeys = await Promise.all(pre_ephKeys);
const pre_gKni = gKCiphers[0].map(async (_, i) => await Promise.all(gKCiphers.map(async (cipher, j) => Point.fromB64(await decryptData(cipher[i], ephKeys[j]))))); // Resolving a double array of promises - quite confusing
const gKni = await Promise.all(pre_gKni);
const gKn = gKni.map(p => p.reduce((sum, next) => sum.add(next)));

// Calculate all lagrange coefficients for all the shards
const ids = orkIds.map(id => BigInt(id));
const lis = ids.map(id => GetLi(id, ids, Point.order));

// Interpolate the key public
const gKntest = sendShardResponses[0].gKtesti.map((_, i) => sendShardResponses.reduce((sum, next, j) => sum.add(next.gKtesti[i].times(lis[j])), Point.infinity));

// Interpolate the gMultipliers
const gMultiplied = sendShardResponses[0].gMultiplied.map((m, i) => m == null ? null : sendShardResponses.reduce((sum, next) => sum.add(next.gMultiplied[i]), Point.infinity));

// Generate the partial EdDSA R
const R2 = sendShardResponses.reduce((sum, next) => sum.add(next.gRi), Point.infinity);

//Check gKntest with gKn
const gKtestCHECK = gKn.every((p, i) => p.isEqual(gKntest[i]));
if(!gKtestCHECK) throw new Error("SendShardReply: GKTest check failed");

return {gKntest: gKntest, R2: R2, gMultiplied: gMultiplied, gKn: gKn, ephKeys: sendShardResponses.map(resp => resp.ephKeyi)};
}

/**
*
* @param {SetKeyResponse[]} setKeyResponses
* @param {string} keyID
* @param {Point[]} gKn
* @param {Point[]} gKntest
* @param {bigint} timestamp
* @param {Point[]} mgORKi
* @param {Point} R2
* @param {bigint} timestamp
* @param {Point} R2
*/
export async function SetKeyValidation(setKeyResponses, keyID, gKn, gKntest, timestamp, mgORKi, R2){
export async function SendShardReply(keyId, sendShardResponses, mgORKi, timestamp, R2){
// Verify all GK1s are the same
if(!sendShardResponses.every(resp => resp.gK1.isEqual(sendShardResponses[0].gK1))) throw new Error("SendShardReply: Not all GK1s returned are the same.");

// Aggregate the signature
const S = mod(setKeyResponses.map(resp => BigInt(resp.S)).reduce((sum, next) => sum + next), Point.order); // sum all responses in finite field of Point.order
const S = mod(sendShardResponses.reduce((sum, next) => next.Si + sum, BigInt(0)));

// Generate EdDSA R from all the ORKs publics
const M_data_to_hash = ConcatUint8Arrays([gKn[0].compress(), StringToUint8Array(timestamp.toString()), StringToUint8Array(keyID)]);
const M_data_to_hash = ConcatUint8Arrays([sendShardResponses[0].gK1.compress(), StringToUint8Array(timestamp.toString()), StringToUint8Array(keyId)]);
const M = await SHA256_Digest(M_data_to_hash);
const R = mgORKi.reduce((sum, next) => sum.add(next)).add(R2);

// Prepare the signature message
const H_data_to_hash = ConcatUint8Arrays([R.compress(), gKntest[0].compress(), M]);
const H_data_to_hash = ConcatUint8Arrays([R.compress(), sendShardResponses[0].gK1.compress(), M]);
const H = mod(BigIntFromByteArray(await SHA512_Digest(H_data_to_hash)), Point.order);

// Verify signature validates
if(!(Point.g.times(S).isEqual(R.add(gKntest[0].times(H))))) throw new Error("SetKeyValidation: Signature test failed");
if(!(Point.g.times(S).isEqual(R.add(sendShardResponses[0].gK1.times(H))))) throw new Error("SendShard: Signature test failed");

// Create Encrypted State list
const encCommitStatei = setKeyResponses.map(resp => resp.EncCommitStatei);
// Interpolate the gMultipliers
const gMultiplied = sendShardResponses[0].gMultiplied.map((m, i) => m == null ? null : sendShardResponses.reduce((sum, next) => sum.add(next.gMultiplied[i]), Point.infinity));

return {S: S, encCommitStatei: encCommitStatei};
return {S: S, encCommitStatei: sendShardResponses.map(resp => resp.encCommitStatei), gMultiplied: gMultiplied};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ import Point from "../Ed25519/point.js"
export default class GenShardResponse{
/**
* @param {string[]} YijCiphers
* @param {string[]} gKnCipher
* @param {Point} GRi
* @param {bigint} Timestampi
*/
constructor(YijCiphers, gKnCipher, Timestampi){
constructor(YijCiphers, GRi, Timestampi){
this.YijCiphers = YijCiphers
this.GKnCipher = gKnCipher
this.GRi = GRi
this.Timestampi = Timestampi
}
static from(data){
const obj = JSON.parse(data);
const timestampi = BigInt(obj.Timestampi);
return new GenShardResponse(obj.YijCiphers, obj.GKnCiphers, timestampi);
const gRi = Point.fromB64(obj.GRi)
return new GenShardResponse(obj.YijCiphers, gRi, timestampi);
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import Point from "../Ed25519/point.js";
import { BigIntFromByteArray, base64ToBytes } from "../Tools/Utils.js";

export default class SendShardResponse{
/**
* @param {Point[]} gKtesti
* @param {Point} gRi
* @param {bigint} Si
* @param {Point} gK1
* @param {string} encCommitStatei
* @param {Point[]} gMultiplied
* @param {string} ephKeyi
*/
constructor(gKtesti, gRi, gMultiplied, ephKeyi){
this.gKtesti = gKtesti
this.gRi = gRi
constructor(Si, gK1, encCommitStatei, gMultiplied){
this.Si = Si
this.gK1 = gK1
this.encCommitStatei = encCommitStatei
this.gMultiplied = gMultiplied
this.ephKeyi = ephKeyi
}

static from(data){
const obj = JSON.parse(data);
const gKtesti = obj.GKntesti.map(p => Point.fromB64(p));
const gRi = Point.fromB64(obj.GRi);
const si = BigIntFromByteArray(base64ToBytes(obj.Si));
const gK1 = Point.fromB64(obj.GK1);
const gMultiplied = obj.GMultiplied.map(p => p == null ? null : Point.fromB64(p));
return new SendShardResponse(gKtesti, gRi, gMultiplied, obj.EphKeyi);
return new SendShardResponse(si, gK1, obj.EncCommitStatei, gMultiplied);
}
}
Loading

0 comments on commit 83edffb

Please sign in to comment.