Compare commits

..

No commits in common. "main" and "frontend" have entirely different histories.

11 changed files with 86 additions and 378 deletions

View File

@ -2,7 +2,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.7.10"
id("org.jetbrains.compose") version "1.2.1"
application
}
@ -11,12 +10,9 @@ version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
google()
}
dependencies {
implementation(compose.desktop.currentOs)
testImplementation(kotlin("test"))
}
@ -28,8 +24,6 @@ tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
application {
mainClass.set("MainKt")
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

View File

@ -1,115 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Flag Submission Page</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.6.1/web3.min.js" integrity="sha512-5erpERW8MxcHDF7Xea9eBQPiRtxbse70pFcaHJuOhdEBQeAxGQjUwgJbuBDWve+xP/u5IoJbKjyJk50qCnMD7A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<head>
<title>Flag Submission Page</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="dist/bundle.js"></script>
</head>
<body style="height:1500px">
<!--<script src="dist/bundle.js"></script>-->
</head>
<body style="height:1500px">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Flag Submission Page</a>
</div>
<ul class="nav navbar-nav">
<li><a href="leaderboard.html">Leaderboard</a></li>
<li class="active"><a href="sendflag.html">Send Flag</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Flag Submission Page</a>
</div>
<ul class="nav navbar-nav">
<li>
<a href="leaderboard.html">Leaderboard</a>
</li>
<li class="active">
<a href="sendflag.html">Send Flag</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><button class="btn btn-default navbar-btn" id="metamask-login" type="button" style="margin-right:20px"><span class="glyphicon glyphicon-log-in"></span> Connect Wallet</button></li>
<!--<button class="btn btn-danger navbar-btn">Button</button>-->
</ul>
</div>
</nav>
<li>
<button class="btn btn-default navbar-btn" id="metamask-login" type="button" style="margin-right:20px">
<span class="glyphicon glyphicon-log-in"></span>
Connect Wallet</button>
</li>
<!--<button class="btn btn-danger navbar-btn">Button</button>-->
</ul>
</div>
</nav>
<div class="container" style="margin-top:50px">
<h1>Send the flag</h1>
<form class="form-inline" id="flag-form" style="display:none">
<div class="form-group">
<label for="flagbox">Flag:</label>
<input type="text" class="form-control" id="flagbox">
</div>
<button id="submitFlagBtn" type="button" class="btn btn-default">Submit Flag</button>
</form>
</div>
<div class="container" style="margin-top:50px">
<h1>Send the flag</h1>
<form class="form-inline" id="flag-form" style="display:none">
<div class="form-group">
<label for="flagbox">Flag id:</label>
<input type="number" class="form-control" id="flagID">
</div>
<div class="form-group">
<label for="flagbox">Proof:</label>
<input type="text" class="form-control" id="flagbox">
</div>
<button id="submitFlagBtn" type="button" class="btn btn-default btn-warning">Submit Flag</button>
</form>
</div>
<script type='module'>
window.addEventListener("load", function () {
let loginbutton = document.getElementById('metamask-login');
let accounts;
ethereum.request({method: 'eth_requestAccounts'}).then(accounts => {
console.log(accounts);
if (accounts.length > 0) {
document.getElementById('flag-form').style.display = "block";
loginbutton.textContent = accounts[0];
loginbutton.disabled = true;
}
});
});
<script type='module'>
var web3js;
var accounts;
const contractAddress = "0x970e1d481CEDbeaeFE776275F0d1b4E1B301bB3b";
window.addEventListener("load", function () {
let loginbutton = document.getElementById('metamask-login');
let loginbutton = document.getElementById('metamask-login');
loginbutton.addEventListener('click', event => {
let account;
ethereum.request({method: 'eth_requestAccounts'}).then(accounts =>{
account = accounts[0];
document.getElementById('flag-form').style.display = "block";
loginbutton.textContent = account;
loginbutton.disabled = true;
})
})
</script>
ethereum.request({method: 'eth_requestAccounts'}).then(acc => {
console.log(acc);
accounts = acc;
if (acc.length > 0) {
document.getElementById('flag-form').style.display = "block";
loginbutton.textContent = accounts[0];
loginbutton.disabled = true;
}
});
});
let loginbutton = document.getElementById('metamask-login');
loginbutton.addEventListener('click', event => {
let account;
ethereum.request({method: 'eth_requestAccounts'}).then(accounts => {
account = accounts[0];
document.getElementById('flag-form').style.display = "block";
loginbutton.textContent = account;
loginbutton.disabled = true;
})
})
let flagID = document.getElementById('flagID');
let flagbox = document.getElementById('flagbox');
let submitFlagBtn = document.getElementById('submitFlagBtn');
submitFlagBtn.addEventListener('click', event => {
contract.methods.SubmitFlag(JSON.parse(flagbox.value),flagID.value).send( { from: accounts[0] });
})
var contactABI;
var contract;
async function getAbi() {
fetch("/abi.json").then(a => a.json().then(abi => {
contactABI = abi
contract = new web3js.eth.Contract(contactABI, contractAddress);
}));
}
window.addEventListener("load", function () {
if (typeof web3 !== "undefined") {
web3js = new Web3(web3.currentProvider);
// console.log(web3);
getAbi();
} else {
console.log("No web3? You should consider trying MetaMask!");
}
});
</script>
</body>
</body>
</html>

View File

@ -1,13 +1,6 @@
import sha256 from 'crypto-js/sha256.js';
import { initialize } from 'zokrates-js';
window.addEventListener('load', () => {
document.getElementById('submitFlagBtn')
.addEventListener('click', () => {
submitFlag(document.getElementById('flagbox').value);
});
});
const ZEROSTR = '0';
/* Converts a string into a stringified hexadecimal number */
@ -61,15 +54,25 @@ function expand_number(number) {
return [...Array(8 - parts.length).fill(ZEROSTR), ...parts];
}
const proving_key = await (await fetch('/zok_proving.key')).text();
const program = await (await fetch('/zok_program')).arrayBuffer();
const abi = await (await fetch('/zok_abi.json')).json();
/* Hard coded zokrates program source code */
const zokSrc = `
import "hashes/sha256/sha256Padded.zok" as sha256;
from "utils/casts.zok" import cast;
def main(public u32[8] hash,public u32[5] address,private u8[64] flag){
u8[20] addr8 = cast(address);
u32[8] genHash = sha256(flag);
log("Hash: {} {} {} {} {} {} {} {}",genHash[0],genHash[1],genHash[2],genHash[3],genHash[4],genHash[5],genHash[6],genHash[7]);
assert(genHash == hash);
return;
}
`;
/* Get the proving key from the local server */
const PROVING_KEY_URI = 'http://localhost:8080/proving.key';
const proving_key = await (await fetch(PROVING_KEY_URI)).text();
const artefacts = { program: new Uint8Array(program), abi: abi };
console.log(artefacts);
function submitFlag(flag) {
initialize().then((defaultProvider) => {
@ -78,6 +81,8 @@ function submitFlag(flag) {
scheme: 'gm17',
});
const artefacts = zokProvider.compile(zokSrc);
const flag_ascii = str2asciiarr(flag);
const flag_ascii_padded = flag_ascii.concat(new Array(64 - flag_ascii.length).fill(0));
const flag_padded = asciiarr2str(flag_ascii_padded);
@ -91,13 +96,15 @@ function submitFlag(flag) {
const addr_split = map_0xprefix(addr.match(/.{1,8}/g));
// witness computation
console.log('witness');
const { witness, output } = zokProvider.computeWitness(artefacts, [hash_split, addr_split, flag_split_padded]);
// generate proof
console.log('proof');
const proof = zokProvider.generateProof(artefacts.program, witness, proving_key);
console.log(proof);
});
};
}
document.getElementById('submitFlagBtn').addEventListener('click', () => {
submitFlag(document.getElementById('flagbox').value);
});

View File

@ -1,37 +0,0 @@
{
"inputs": [
{
"name": "hash",
"public": true,
"type": "array",
"components": {
"size": 8,
"type": "u32"
}
},
{
"name": "address",
"public": true,
"type": "array",
"components": {
"size": 5,
"type": "u32"
}
},
{
"name": "flag",
"public": false,
"type": "array",
"components": {
"size": 64,
"type": "u8"
}
}
],
"output": {
"type": "tuple",
"components": {
"elements": []
}
}
}

View File

@ -1,94 +1,8 @@
package hu.bmeta.cctf
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
fun main() {
Zokrates.initZokrates()
application {
Window(
onCloseRequest = ::exitApplication,
title = "ZoKrates CTF Proof generator",
state = rememberWindowState(width = 300.dp, height = 300.dp)
) {
val count = remember { mutableStateOf(0) }
val address = remember { mutableStateOf("") }
val flag = remember { mutableStateOf("") }
val enabled = remember { mutableStateOf(true) }
MaterialTheme {
Column(Modifier.fillMaxSize().padding(5.dp), Arrangement.spacedBy(5.dp)) {
Text("ZoKrates Proof generator")
OutlinedTextField(address.value, {
address.value = it
}, placeholder = {
Text("Address")
})
OutlinedTextField(flag.value, {
flag.value = it
}, placeholder = {
Text("Flag")
})
Button(modifier = Modifier.align(Alignment.CenterHorizontally),
onClick = {
enabled.value = false
val address_ch = address.value.replace("0x","").chunked(8).map { java.lang.Long.parseLong(it.uppercase(),16).toString() }
val message = flag.value.map { it.code.toByte().toInt().toString() }.toMutableList()
for (i in 0 until 64 - message.size) {
message.add("0")
}
val hashArgs = mutableListOf<String>()
hashArgs.addAll(address_ch)
hashArgs.addAll(message)
GlobalScope.launch(Dispatchers.IO) {
Zokrates.compile("hash.zok","hash")
val result = Zokrates.computeWithness(hashArgs,"hash")
println(result)
val zkpArgs = mutableListOf<String>()
zkpArgs.addAll(result)
zkpArgs.addAll(address_ch)
zkpArgs.addAll(message)
Zokrates.compile("root.zok")
val results2 = Zokrates.computeWithness(zkpArgs)
println(results2)
Zokrates.generateProof(scheme = Zokrates.ProvingScheme.GM17)
println("Proof done!")
}
enabled.value = true
}, enabled = enabled.value) {
Text("Generate Proof!")
}
if(enabled.value.not()){
CircularProgressIndicator()
}
}
}
}
}
}
/*fun main() {
val address = listOf("1530452586","1880905349","1172110512","1070303071","1455349188")
val message = mutableListOf("116", "101", "115","116","0")
val random = Random()
for(i in 0 until 64-message.size){
message.add("0")
}
val message = listOf("104","116","116","112","115","58","47","47","119","119","119","46","121","111","117","116","117","98","101","46","99","111","109","47","119","97","116","99","104","63","118","61","100","81","119","52","119","57","87","103","88","99","81","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0")
Zokrates.initZokrates()
Zokrates.compile("hash.zok","hash")
val hashArgs = mutableListOf<String>()
@ -109,4 +23,4 @@ fun main() {
Zokrates.generateProof(scheme = Zokrates.ProvingScheme.GM17)
Zokrates.verify()
}*/
}

View File

@ -1,54 +0,0 @@
# Kusamaverse Proposal
- Authors: {Péter Bertalan, Nagymarosi Máté, Toldi Balázs, Debreczeni Máté}
- Status: {Draft}
- Created: {2022-12-07}
## Summary
Our first proposal is to create more comprehensive learning materials, because we found the
UX clarity to be somewhat lacking. It shall convey the values and objectives of the platform
clearly. Kusamaverse needs to improve its authentication and authorization capabilities.
## Motivation
In our experience, Kusamaverse is hard to understand for new users. The user's first impressions are
important, but in the current version it is formed by marketing materials and forms. The user is not
presented with what the platform provides and how it can be used.
## Specification
proposed changes:
1. Game-like guided learning experience
2. Guide/Mascot character
3. Written materials, stories, and resources
4. The integration of authorization and authentication
### 1. Game-like guided learning experience
Most games start with a introductory quest, which eases the player into the in-game environment.
Kusamaverse would greatly benefit from such an addition. The user would receive valuable context
via a story told by an "in-game" character.
### 2. Guide/Mascot character
A fun mascot that could introduce the player to the Kusamaverse environment. It would always
be avaliable to offer guidance, especially during the first steps. Instead of forms, initial
user preferences could be attained through conversation with the mascot. The objective is to
make the process as fun as possible.
### 3. Written materials, stories, resources
Even after deliberate searching, information about the Kusamaverse was hard to find. For those
that are interested in the background, easily digestable materials should be made more avaliable.
### 4. The integration of authorization and authentication
To the best of our knowledge, currently there is no way to ensure that only select people can
attend a space. Collaboration can be enhanced by limiting unwanted access, which can degrade
the experience.

View File

@ -1,23 +0,0 @@
# BMEta solutions
## Proposals
### 1. Kusamaverse
Our proposal focuses on usability and UX.
It can be found [here](./Kusamaverse_Proposal).
### 2. RMRK
We propose a few [improvements and enhancements ](./RMRK_Proposal) to
the ticketing sytem use case of RMRK.
## Main track: CCTF
We were presented with a vulnerable Capture The Flag
smart contract, which we fixed by the help of ZKPs.
Using ZKPs allows some unique features and it could
help provide the community with new and exciting
ways to organize CTF events. The solution can be found
[here](./CCTF_Solutions_main).

View File

@ -1,47 +0,0 @@
# RMRK Proposal
- Authors: {Péter Bertalan, Nagymarosi Máté, Toldi Balázs, Debreczeni Máté}
- Status: {Draft}
- Created: {2022-12-07}
## Summary
The RMRK documentation currently includes a use case description of a
ticketing system, built on revealable and multi-resource NFTs.
We extend this application with a few additional ideas that take
advantage of RMRKs toolbox.
## Motivation
Classic solutions to ticketing come with their drawbacks. RMRK offers
new and versatile building blocks for making NFTs more powerful and
rich, while also eliminating a lot of the downsides. However, one aspect
not addressed by the current draft is scalping. Scalping is the practice
of buying large amounts of a scarce asset to resell it at a higher
price. Even centralized systems struggle to combat this issue. Our
proposal offers a possible mitigation.
## Specification
### Multi-use tickets
Instead of following the traditional scheme of one ticket per event, a
ticket could possibly be valid for a number of select or arbitrary
events. In this case, ticket validation would entail verifying a counter
or the presence of a specific PoA besides the secret keyword.
### A loyalty system
Dedicated fans deserve extra perks for their support. Our proposal
utilizes multi-resource NFTs to enable customers to attain a collection
of PoAs as part of a single NFT. This could be used to set up the basis
of a loyalty system. Owners of such collections would be able to
participate in presales, ensuring that they dont miss out on their
favourite event.
### Scalping mitigation
The loyalty system outlined already offers some level of protection
against scalpers, but we would further enhance this with the use of
Verifiable Credentials. These could be issued by a trusted organization
and the amount of tickets per capita could be limited.