diff --git a/contracts/AbstractBounty.sol b/contracts/AbstractBounty.sol new file mode 100644 index 0000000..ab81f09 --- /dev/null +++ b/contracts/AbstractBounty.sol @@ -0,0 +1,64 @@ +pragma solidity ^0.4.8; + +/** + * + */ + +contract AbstractBounty { + + uint public constant LOCKED_TIME = 30 days; + + mapping (address => mapping(uint => uint)) deposits; + mapping (uint => Issue) issues; + + struct Issue { + uint balance; + uint unlock; + address claimer; + bool claimed; + } + + modifier only_unlocked(uint num){ + if(issues[num].unlock == 0 || issues[num].unlock > now) throw; + } + + modifier only_unclaimed(uint num){ + if(issues[num].claimed) throw; + } + + function deposit(uint num) + only_unclaimed(num) + payable { + deposits[msg.sender][num] += msg.value; + issues[num].balance += msg.value; + } + + function withdraw(uint num) + only_unlocked(num) + only_unclaimed(num) { + uint avaliable = deposits[msg.sender][num]; + deposits[msg.sender][num] -= avaliable; + issues[num].balance -= avaliable; + msg.sender.send(avaliable); + } + + function open(uint num) + only_unlocked(num) + internal { + issues[num].unlock=0; + } + function close(uint num) + only_unlocked(num) + internal { + issues[num].unlock=now+LOCKED_TIME; + } + + function claim(uint num) + only_unlocked(num) + only_unclaimed(num) { + issues[num].claimer = msg.sender; + issues[num].claimed = true; + if(!msg.sender.send(issues[num].balance)) throw; + } + + } \ No newline at end of file diff --git a/contracts/AbstractCoin.sol b/contracts/AbstractToken.sol similarity index 93% rename from contracts/AbstractCoin.sol rename to contracts/AbstractToken.sol index 18b1b25..771a941 100644 --- a/contracts/AbstractCoin.sol +++ b/contracts/AbstractToken.sol @@ -1,7 +1,7 @@ -pragma solidity ^0.4.1; +pragma solidity ^0.4.8; /** - * AbstractCoin ECR20-compliant token contract + * AbstractToken ECR20-compliant token contract * Child should implement initial supply or minting and overwite base * Based on BasicCoin by Parity Team (Ethcore), 2016. * By Ricardo Guilherme Schmidt @@ -10,8 +10,8 @@ pragma solidity ^0.4.1; import "Token.sol"; -// AbstractCoin, ECR20 tokens that all belong to the owner for sending around -contract AbstractCoin is Token { +// AbstractToken, ECR20 tokens that all belong to the owner for sending around +contract AbstractToken is Token { // the base, tokens denoted in micros uint constant public base = 0; diff --git a/contracts/CollaborationToken.sol b/contracts/CollaborationToken.sol new file mode 100644 index 0000000..88da594 --- /dev/null +++ b/contracts/CollaborationToken.sol @@ -0,0 +1,158 @@ +pragma solidity ^0.4.0; + +/** + * Abstract contract used for recieving donations or profits + * Withdraw is divided by total tokens each account owns + * Unlock period allows transfers + * Lock period allow withdraws + * Child contract that implement minting should use modifier not_locked in minting function + * Inspired by ProfitContainer and Lockable by vDice + * + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "AbstractToken.sol"; + +contract CollaborationToken is AbstractToken { + //creation time, defined when contract is created + uint public creationTime = now; + //time constants, defines epoch size and periods + uint public constant UNLOCKED_TIME = 25 days; + uint public constant LOCKED_TIME = 5 days; + uint public constant EPOCH_LENGTH = UNLOCKED_TIME + LOCKED_TIME; + //current epoch constant formula, recalculated in any contract call + uint public constant CURRENT_EPOCH = (now - creationTime) / EPOCH_LENGTH + 1; + //next lock constant formula, recalculated in any contract call + uint public constant NEXT_LOCK = (creationTime + CURRENT_EPOCH * UNLOCKED_TIME) + (CURRENT_EPOCH - 1) * LOCKED_TIME; + //used for calculating balance and for checking if account withdrawn + uint public currentPayEpoch; + //stores the balance from the lock time + uint public epochBalance; + //stores lock state, used for events + bool public lock; + //used for hecking if account withdrawn + mapping (address => uint) lastPaidOutEpoch; + //events + event Withdrawn(address tokenHolder, uint amountPaidOut); + event Deposited(address donator,uint value); + event Locked(); + event Unlocked(); + + //checks if not locked and call event on change + modifier not_locked { + if (NEXT_LOCK < now) { + if (lock) throw; + lock = true; + Locked(); + return; + } + else { + if (lock) { + lock = false; + Unlocked(); + } + } + _; + } + + //checks if is locked and call event on change + modifier locked { + if (NEXT_LOCK < now) { + if (!lock){ + lock = true; + Locked(); + } + } + else { + if (!lock) throw; + lock = false; + Unlocked(); + return; + } + _; + } + + //update the balance and payout epoch + modifier update_epoch { + if(currentPayEpoch < CURRENT_EPOCH) { + currentPayEpoch = CURRENT_EPOCH; + epochBalance = this.balance; + } + _; + } + + //checks if user already withdrawn + modifier not_paid { + if (lastPaidOutEpoch[msg.sender] == currentPayEpoch) throw; + _; + } + + //check overflow in multiply + modifier safe_multiply(uint _a, uint _b) { + if (!(_b == 0 || ((_a * _b) / _b) == _a)) throw; + _; + } + + //allow deposit and call event + function () + payable { + Deposited(msg.sender, msg.value); + } + + //withdraw if locked and not paid, updates epoch + function withdrawal() + external + locked + update_epoch + not_paid + safe_multiply(balanceOf(msg.sender), epochBalance) { + uint _currentEpoch = CURRENT_EPOCH; + uint _tokenBalance = balanceOf(msg.sender); + uint _totalSupply = totalSupply; + if (this.balance == 0 || _tokenBalance == 0) throw; + lastPaidOutEpoch[msg.sender] = currentPayEpoch; + uint amountToPayOut = (_tokenBalance * epochBalance) / _totalSupply; + if(!msg.sender.send(amountToPayOut)) { + throw; + } + Withdrawn(msg.sender, amountToPayOut); + } + + //if this coin owns tokens of other lockablecoin, allow withdraw + function withdrawalFrom(CollaborationToken _otherCollaborationToken) { + _otherCollaborationToken.withdrawal(); + } + + //return expected payout in lock or estimated when not locked + function expectedPayout(address _tokenHolder) + external + constant + returns (uint payout) { + if (now < NEXT_LOCK) //unlocked, estimate + payout = (balanceOf(_tokenHolder) * this.balance) / totalSupply; + else + payout = (balanceOf(_tokenHolder) * epochBalance) / totalSupply; + } + + //overwrite not allow transfer during lock + function transfer(address _to, uint256 _value) + not_locked + returns (bool ok) { + return super.transfer(_to,_value); + } + + //overwrite not allow transfer during lock + function transferFrom(address _from, address _to, uint256 _value) + not_locked + returns (bool ok) { + return super.transferFrom(_from,_to,_value); + } + + //overwrite not allow transfer during lock + function approve(address _spender, uint256 _value) + returns (bool ok) { + return super.approve(_spender,_value); + } + +} diff --git a/contracts/GitHubIssue.sol b/contracts/GitHubIssue.sol new file mode 100644 index 0000000..fd030e8 --- /dev/null +++ b/contracts/GitHubIssue.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.4.8; + +/** + * + */ + import "Bounty.sol"; + + contract GitHubIssue is AbstractBounty { + + + function __callback(bytes32 _ocid, string _result) { + + } + + function update(uint num){ + + + } + } \ No newline at end of file diff --git a/contracts/GithubToken.sol b/contracts/GithubToken.sol index 5b63abc..3aa7928 100644 --- a/contracts/GithubToken.sol +++ b/contracts/GithubToken.sol @@ -17,25 +17,21 @@ pragma solidity ^0.4.8; */ import "lib/oraclizeAPI_0.4.sol"; -import "LockableCoin.sol"; +import "Owned.sol"; +import "CollaborationToken.sol"; + +contract GitHubToken is CollaborationToken, usingOraclize { -contract GitHubToken is LockableCoin, usingOraclize { - //constant for oraclize commits callbacks - uint8 constant CALLBACK_CLAIMCOMMIT = 1; //stores repository name, used for claim calls string private repository; //stores repository name in sha3, used by GitHubOracle bytes32 public sha3repository; - //temporary storage enumerating oraclize calls - mapping (bytes32 => uint8) oraclize_type; - //temporary storage for oraclize commit token claim calls - mapping (bytes32 => string) oraclize_claim; //permanent storage of recipts of all commits mapping (bytes32 => CommitReciept) public commits; //Address of the oracle, used for github login address lookup GitHubOracle public oracle; //claim event - event Claim(address claimer, string commitid, uint total); + event Claim(string claimer, string commitid, uint total); //stores the total and user, and if claimed (used against double claiming) struct CommitReciept { @@ -50,6 +46,11 @@ contract GitHubToken is LockableCoin, usingOraclize { _; } + modifier only_oracle { + if (msg.sender != address(oracle)) throw; + _; + } + function GitHubToken(string _repository, GitHubOracle _oracle) payable { oracle = _oracle; @@ -64,35 +65,21 @@ contract GitHubToken is LockableCoin, usingOraclize { return commits[sha3(_commitid)].claimed; } - //oraclize response callback - function __callback(bytes32 _ocid, string _result) { - if (msg.sender != oraclize_cbAddress()) throw; - uint8 callback_type = oraclize_type[_ocid]; - if(callback_type==CALLBACK_CLAIMCOMMIT && !lock){ - _claim(_ocid,_result); - } - delete oraclize_type[_ocid]; - } - - //oraclize callback claim request - function _claim(bytes32 _ocid, string _result) - internal { - var (login,total) = extract(_result); - address user = oracle.getUserAddress(login); - if(user != 0x0){ - commits[sha3(oraclize_claim[_ocid])].user = user; - if(total > 0){ - bytes32 shacommit = sha3(oraclize_claim[_ocid]); - commits[shacommit].total = total; - if(commits[shacommit].user != 0x0 && !commits[shacommit].claimed){ - commits[shacommit].claimed = true; - accounts[user].balance += total; - totalSupply += total; - Claim(user,oraclize_claim[_ocid],total); - } + //oracle claim request + function _claim(string _commitid, string _login, uint _total) + only_oracle { + if(_total > 0 && !lock){ + bytes32 shacommit = sha3(_commitid); + address user = oracle.getUserAddress(_login); + if(!commits[shacommit].claimed && user != 0x0){ + commits[shacommit].claimed = true; + commits[shacommit].user = user; + commits[shacommit].total = _total; + accounts[user].balance += _total; + totalSupply += _total; + Claim(_login,_commitid,_total); } } - delete oraclize_claim[_ocid]; } //claims a commitid @@ -100,13 +87,130 @@ contract GitHubToken is LockableCoin, usingOraclize { payable not_locked not_claimed(_commitid) { - bytes32 ocid = oraclize_query("URL", strConcat("json(https://api.github.com/repos/", repository,"/commits/", _commitid,").[author,stats].[login,total]")); - oraclize_type[ocid] = CALLBACK_CLAIMCOMMIT; - oraclize_claim[ocid] = _commitid; + oracle.claimCommit(repository, _commitid); } +} + +contract GitHubOracle is Owned, usingOraclize { + //constant for oraclize commits callbacks + uint8 constant CLAIM_USER = 0; + //constant for oraclize commits callbacks + uint8 constant CLAIM_COMMIT = 1; + //temporary storage enumerating oraclize calls + mapping (bytes32 => uint8) claimType; + //temporary storage for oraclize commit token claim calls + mapping (bytes32 => CommitClaim) commitClaim; + //temporary storage for oraclize user register queries + mapping (bytes32 => UserClaim) userClaim; + //permanent storage of sha3(login) of github users + mapping (bytes32 => address) users; + //permanent storage of registered repositories + mapping (bytes32 => Repository) repositories; + //store encrypted values of api access credentials + string private credentials = ""; + //events + event UserSet(string githubLogin, address account); + event RepositoryAdd(string repository, address account); + + //stores the address of githubtoken and registered is used for overwriting previous registered + struct Repository { + GitHubToken account; + bool registered; + } + + //stores temporary data for oraclize user register request + struct UserClaim { + address sender; + bytes32 githubid; + string login; + } + //stores temporary data for oraclize repository commit claim + struct CommitClaim { + bytes32 repository; + string commitid; + } + + //return the address of a github login + function getUserAddress(string _login) + external + constant + returns (address) { + return users[sha3(_login)]; + } + + //oraclize response callback + function __callback(bytes32 _ocid, string _result) { + if (msg.sender != oraclize_cbAddress()) throw; + uint8 callback_type = claimType[_ocid]; + if(callback_type==CLAIM_USER){ + if(strCompare(_result,"404: Not Found") != 0){ + address githubowner = parseAddr(_result); + if(userClaim[_ocid].sender == githubowner){ + _register(userClaim[_ocid].githubid,userClaim[_ocid].login,githubowner); + } + } + delete userClaim[_ocid]; //should always be deleted + }else if(callback_type==CLAIM_COMMIT){ + var (login,total) = extractCommit(_result); + repositories[commitClaim[_ocid].repository].account._claim(commitClaim[_ocid].commitid,login,total); + delete commitClaim[_ocid]; //should always be deleted + } + delete claimType[_ocid]; //should always be deleted + } + + + function _register(bytes32 githubid, string login, address githubowner) + internal { + users[githubid] = githubowner; + UserSet(login, githubowner); + } + + //register or change a github user ethereum address + function register(string _github_user, string _gistid) + payable { + bytes32 ocid = oraclize_query("URL", strConcat("https://gist.githubusercontent.com/",_github_user,"/",_gistid,"/raw/")); + claimType[ocid] = CLAIM_USER; + userClaim[ocid] = UserClaim({sender: msg.sender, githubid: sha3(_github_user), login: _github_user}); + } + + function claimCommit(string _repository, string _commitid) + payable { + bytes32 ocid = oraclize_query("URL", strConcat(strConcat("json(https://api.github.com/repos/", _repository,"/commits/", _commitid, credentials),").[author,stats].[login,total]")); + claimType[ocid] = CLAIM_COMMIT; + commitClaim[ocid] = CommitClaim({repository: sha3(_repository), commitid: _commitid }); + } + + //creates a new GitHubToken contract to _repository + function addRepository(string _repository) + returns (GitHubToken) { + bytes32 repo = sha3(_repository); + if(repositories[repo].registered) throw; + repositories[repo] = Repository({account: new GitHubToken(_repository, this), registered: true}); + RepositoryAdd(_repository, repositories[repo].account); + return repositories[repo].account; + } + + //register a contract deployed outside Oracle + function addRepository(string _repository, GitHubToken _addr) + returns (GitHubToken) { + bytes32 repo = sha3(_repository); + if(repositories[repo].registered || _addr.sha3repository() != repo) throw; + repositories[repo] = Repository({account: _addr, registered: true}); + RepositoryAdd(_repository, repositories[repo].account); + return repositories[repo].account; + } + + //return the contract address of the repository (or 0x0 if none registered) + function getRepository(string _repository) + constant + returns (GitHubToken) { + return repositories[sha3(_repository)].account; + } + + //extract login name and total of changes in commit - function extract(string _s) + function extractCommit(string _s) internal constant returns (string login,uint total) { @@ -143,93 +247,14 @@ contract GitHubToken is LockableCoin, usingOraclize { } } } -} - -contract GitHubOracle is usingOraclize { - //constant for oraclize commits callbacks - uint8 constant CALLBACK_REGISTER = 0; - //temporary storage enumerating oraclize calls - mapping (bytes32 => uint8) oraclize_type; - //temporary storage for oraclize user register queries - mapping (bytes32 => VerifyRequest) oraclize_register; - //permanent storage of sha3(login) of github users - mapping (bytes32 => address) github_users; - //permanent storage of registered repositories - mapping (bytes32 => Repository) repositories; - //events - event UserSet(string githubLogin, address account); - event RepositoryAdd(string repository, address account); - - //stores the address of githubtoken and registered is used for overwriting previous registered - struct Repository { - GitHubToken account; - bool registered; - } - - //stores data for oraclize user register request - struct VerifyRequest { - address sender; - bytes32 githubid; - string login; - } - - //return the address of a github login - function getUserAddress(string _login) - external - constant - returns (address) { - return github_users[sha3(_login)]; + + function setAPICredentials(string _client_id, string _client_secret) + only_owner { + credentials = strConcat("?client_id=${[decrypt] ",_client_id,"}&client_secret=${[decrypt] ",_client_secret,"}"); } - - //oraclize response callback - function __callback(bytes32 _ocid, string result) { - if (msg.sender != oraclize_cbAddress()) throw; - uint8 callback_type = oraclize_type[_ocid]; - if(callback_type==CALLBACK_REGISTER){ - if(strCompare(result,"404: Not Found") != 0){ - address githubowner = parseAddr(result); - if(oraclize_register[_ocid].sender == githubowner){ - github_users[oraclize_register[_ocid].githubid] = githubowner; - UserSet(oraclize_register[_ocid].login, githubowner); - } - } - delete oraclize_register[_ocid]; - } - delete oraclize_type[_ocid]; - } - - //register or change a github user ethereum address - function register(string _github_user, string _gistid) - payable { - bytes32 ocid = oraclize_query("URL", strConcat("https://gist.githubusercontent.com/",_github_user,"/",_gistid,"/raw/")); - oraclize_type[ocid] = CALLBACK_REGISTER; - oraclize_register[ocid] = VerifyRequest({sender: msg.sender, githubid: sha3(_github_user), login: _github_user}); - } - - //creates a new GitHubToken contract to _repository - function addRepository(string _repository) - returns (GitHubToken) { - bytes32 repo = sha3(_repository); - if(repositories[repo].registered) throw; - repositories[repo] = Repository({account: new GitHubToken(_repository, this), registered: true}); - RepositoryAdd(_repository, repositories[repo].account); - return repositories[repo].account; - } - //register a contract deployed outside Oracle - function addRepository(string _repository, GitHubToken _addr) - returns (GitHubToken) { - bytes32 repo = sha3(_repository); - if(repositories[repo].registered || _addr.sha3repository() != repo) throw; - repositories[repo] = Repository({account: _addr, registered: true}); - RepositoryAdd(_repository, repositories[repo].account); - return repositories[repo].account; - } - - //return the contract address of the repository (or 0x0 if none registered) - function getRepository(string _repository) - constant - returns (GitHubToken) { - return repositories[sha3(_repository)].account; - } + function clearAPICredentials() + only_owner { + credentials = ""; + } } diff --git a/contracts/LockableCoin.sol b/contracts/LockableCoin.sol index 7a37d8b..b599eab 100644 --- a/contracts/LockableCoin.sol +++ b/contracts/LockableCoin.sol @@ -1,158 +1 @@ -pragma solidity ^0.4.0; - -/** - * Abstract contract used for recieving donations or profits - * Withdraw is divided by total tokens each account owns - * Unlock period allows transfers - * Lock period allow withdraws - * Child contract that implement minting should use modifier not_locked in minting function - * Inspired by ProfitContainer and Lockable by vDice - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "AbstractCoin.sol"; - -contract LockableCoin is AbstractCoin { - //creation time, defined when contract is created - uint public creationTime = now; - //time constants, defines epoch size and periods - uint public constant UNLOCKED_TIME = 25 days; - uint public constant LOCKED_TIME = 5 days; - uint public constant EPOCH_LENGTH = UNLOCKED_TIME + LOCKED_TIME; - //current epoch constant formula, recalculated in any contract call - uint public constant CURRENT_EPOCH = (now - creationTime) / EPOCH_LENGTH + 1; - //next lock constant formula, recalculated in any contract call - uint public constant NEXT_LOCK = (creationTime + CURRENT_EPOCH * UNLOCKED_TIME) + (CURRENT_EPOCH - 1) * LOCKED_TIME; - //used for calculating balance and for checking if account withdrawn - uint public currentPayEpoch; - //stores the balance from the lock time - uint public epochBalance; - //stores lock state, used for events - bool public lock; - //used for hecking if account withdrawn - mapping (address => uint) lastPaidOutEpoch; - //events - event Withdrawn(address tokenHolder, uint amountPaidOut); - event Deposited(address donator,uint value); - event Locked(); - event Unlocked(); - - //checks if not locked and call event on change - modifier not_locked { - if (NEXT_LOCK < now) { - if (lock) throw; - lock = true; - Locked(); - return; - } - else { - if (lock) { - lock = false; - Unlocked(); - } - } - _; - } - - //checks if is locked and call event on change - modifier locked { - if (NEXT_LOCK < now) { - if (!lock){ - lock = true; - Locked(); - } - } - else { - if (!lock) throw; - lock = false; - Unlocked(); - return; - } - _; - } - - //update the balance and payout epoch - modifier update_epoch { - if(currentPayEpoch < CURRENT_EPOCH) { - currentPayEpoch = CURRENT_EPOCH; - epochBalance = this.balance; - } - _; - } - - //checks if user already withdrawn - modifier not_paid { - if (lastPaidOutEpoch[msg.sender] == currentPayEpoch) throw; - _; - } - - //check overflow in multiply - modifier safe_multiply(uint _a, uint _b) { - if (!(_b == 0 || ((_a * _b) / _b) == _a)) throw; - _; - } - - //allow deposit and call event - function () - payable { - Deposited(msg.sender, msg.value); - } - - //withdraw if locked and not paid, updates epoch - function withdrawal() - external - locked - update_epoch - not_paid - safe_multiply(balanceOf(msg.sender), epochBalance) { - uint _currentEpoch = CURRENT_EPOCH; - uint _tokenBalance = balanceOf(msg.sender); - uint _totalSupply = totalSupply; - if (this.balance == 0 || _tokenBalance == 0) throw; - lastPaidOutEpoch[msg.sender] = currentPayEpoch; - uint amountToPayOut = (_tokenBalance * epochBalance) / _totalSupply; - if(!msg.sender.send(amountToPayOut)) { - throw; - } - Withdrawn(msg.sender, amountToPayOut); - } - - //if this coin owns tokens of other lockablecoin, allow withdraw - function withdrawalFrom(LockableCoin _otherLockableCoin) { - _otherLockableCoin.withdrawal(); - } - - //return expected payout in lock or estimated when not locked - function expectedPayout(address _tokenHolder) - external - constant - returns (uint payout) { - if (now < NEXT_LOCK) //unlocked, estimate - payout = (balanceOf(_tokenHolder) * this.balance) / totalSupply; - else - payout = (balanceOf(_tokenHolder) * epochBalance) / totalSupply; - } - - //overwrite not allow transfer during lock - function transfer(address _to, uint256 _value) - not_locked - returns (bool ok) { - return super.transfer(_to,_value); - } - - //overwrite not allow transfer during lock - function transferFrom(address _from, address _to, uint256 _value) - not_locked - returns (bool ok) { - return super.transferFrom(_from,_to,_value); - } - - //overwrite not allow transfer during lock - function approve(address _spender, uint256 _value) - returns (bool ok) { - return super.approve(_spender,_value); - } - -} +Moved to: https://github.com/ethereans/github-token/blob/master/contracts/CollaborationToken.sol \ No newline at end of file diff --git a/contracts/Owned.sol b/contracts/Owned.sol new file mode 100644 index 0000000..f7e0327 --- /dev/null +++ b/contracts/Owned.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.8; + +contract Owned { + + address public owner= msg.sender; + + modifier only_owner { + if (msg.sender != owner) throw; + _; + } +} \ No newline at end of file diff --git a/encrypted_queries_tools.py b/encrypted_queries_tools.py new file mode 100644 index 0000000..09e7533 --- /dev/null +++ b/encrypted_queries_tools.py @@ -0,0 +1,143 @@ +from __future__ import absolute_import +import os +import argparse +import sys +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.kdf import x963kdf +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.ciphers import Cipher,algorithms,modes +from cryptography.hazmat.backends import default_backend +import base64 +import base58 + +backend = default_backend() + +def hex_to_key(pub_key_hex): + pub_key_hex = pub_key_hex.strip() + pub_key_point = pub_key_hex.decode('hex') + public_numbers = ec.EllipticCurvePublicNumbers.from_encoded_point(ec.SECP256K1(), pub_key_point) + public_key = public_numbers.public_key(backend) + return public_key + +def hex_to_priv_key(priv_key_hex, public_key_hex): + priv_key_value = long(priv_key_hex, 16) + public_key = hex_to_key(public_key_hex) + public_numbers = public_key.public_numbers() + private_numbers = ec.EllipticCurvePrivateNumbers(priv_key_value, public_numbers) + priv_key = private_numbers.private_key(backend) + return priv_key + +# Hybrid Encryption Scheme: +# - We perform a Elliptic Curves Diffie-Hellman Key Exchange using: +# - SECP256K1 as curve for key generation +# - ANSI X9.63 KDF as Key Derivation Function to derive the shared secret +# - The symmetric cipher is an AES256.MODE_GCM with authentication tag 16-byte +# of length. Since the key is used only once, we can pick the known nonce/iv +# '000000000000' (96 bits of length). We return concatenation of the encoded +# point, the tag and the ciphertext + +def encrypt(message, receiver_public_key): + sender_private_key = ec.generate_private_key(ec.SECP256K1(), backend) + shared_key = sender_private_key.exchange(ec.ECDH(), receiver_public_key) + sender_public_key = sender_private_key.public_key() + point = sender_public_key.public_numbers().encode_point() + iv = '000000000000' + xkdf = x963kdf.X963KDF( + algorithm = hashes.SHA256(), + length = 32, + sharedinfo = '', + backend = backend + ) + key = xkdf.derive(shared_key) + encryptor = Cipher( + algorithms.AES(key), + modes.GCM(iv), + backend = backend + ).encryptor() + ciphertext = encryptor.update(message) + encryptor.finalize() + return point + encryptor.tag + ciphertext + + +def decrypt(message, receiver_private_key): + point = message[0:65] + tag = message[65:81] + ciphertext = message[81:] + sender_public_numbers = ec.EllipticCurvePublicNumbers.from_encoded_point(ec.SECP256K1(), point) + sender_public_key = sender_public_numbers.public_key(backend) + shared_key = receiver_private_key.exchange(ec.ECDH(), sender_public_key) + iv = '000000000000' + xkdf = x963kdf.X963KDF( + algorithm = hashes.SHA256(), + length = 32, + sharedinfo = '', + backend = backend + ) + key = xkdf.derive(shared_key) + decryptor = Cipher( + algorithms.AES(key), + modes.GCM(iv,tag), + backend = backend + ).decryptor() + message = decryptor.update(ciphertext) + decryptor.finalize() + return message + + +def main(): + parser = argparse.ArgumentParser(description='Encrypt messages to Oraclize using Elliptic Curve Integrated Encryption Scheme.') + parser.add_argument('-e', '--encrypt', dest='mode', action='store_const', const='encrypt', help='Encrypt a string. Requires -p') + parser.add_argument('-p', '--with-public-key', dest='public_key', action='store', help='Use the provided hex-encoded public key to encrypt') + parser.add_argument('-d', '--decrypt', dest='mode', action='store_const', const='decrypt', help='Decrypt a string. Provide private key in Wallet Import Format in standard input, or first line of standard input if encrypted text is also provided on standard input. DO NOT PUT YOUR PRIVATE KEY ON THE COMMAND LINE.') + parser.add_argument('-g', '--generate', dest='mode', action='store_const', const='generate', help='Generates a public and a private key') + parser.add_argument('text', nargs='?', action='store', help='String to encrypt, decrypt. If not specified, standard input will be used.') + + args = parser.parse_args() + + if args.mode != 'encrypt' and args.mode != 'decrypt' and args.mode != 'generate': + parser.print_help() + return + + if args.mode == 'encrypt' and not args.public_key: + print "Please, provide a valid public key" + return + + if args.mode == 'encrypt': + if args.public_key: + pub_key = hex_to_key(args.public_key) + + if args.text: + print base64.b64encode(encrypt(args.text, pub_key)) + return + else: + print base64.b64encode(encrypt(sys.stdin.read(), pub_key)) + return + elif args.mode == 'decrypt': + if args.text: + print "Insert your public key" + public_key = sys.stdin.read() + print "Insert your private key:" + private_key = sys.stdin.read() + private_key = hex_to_priv_key(private_key, public_key) + text = base64.b64decode(args.text) + else: + print "Insert your public key" + public_key = sys.stdin.read() + print "\nInsert your private key:" + private_key = sys.stdin.read() + private_key = hex_to_priv_key(private_key, public_key) + print "\nInsert encrypted text" + text = base64.b64decode(sys.stdin.read()) + + print decrypt(text, private_key) + + if args.mode == 'generate': + receiver_private_key = ec.generate_private_key(ec.SECP256K1(), backend) + receiver_public_key = receiver_private_key.public_key() + number = receiver_private_key.private_numbers() + print "Public Key:", receiver_public_key.public_numbers().encode_point().encode('hex') + print "Private Key:", hex(number.private_value) + + + + +if __name__ == "__main__": + main() diff --git a/scenarios/RegCreateClaim.yaml b/scenarios/RegCreateClaim.yaml index 6ca8f5d..16ca712 100644 --- a/scenarios/RegCreateClaim.yaml +++ b/scenarios/RegCreateClaim.yaml @@ -5,7 +5,16 @@ # - +# Call method setAPICredentials(string,string) +- from: '0x1081108d14493ead0d4071cc757688ed7b111c32' + to: '0x838ef69e5948e423db15757059d538b5bcaf659e' + value: '0x0' + call: 'setAPICredentials(string,string)' + args: + - >- + BLX/GHYsFjUNDKfRXSmJAGDrwzO3p1XFpK2DG9nwRHJ0wHMTA7K4wMj+eoKWc6HpkXnxwn/mC8GPsz3bbPnM6luWa7qLHdT94bQX4g19icuzgfm/4BkY6oK/EUhoE8IU34frpF4= + - >- + BEMxXob2oNvdvo44KXhyBgou2xqr0Lits2wCy/OzrAIsfg5HO+GOEhdcEYrEByjhQosAJJX7uvuj7GVH65J8X7IFUFLrvWabWdTmPIEXwXoBGeU67z6SUtzOOgvAvFKixfl8pAWCDacJGZVQOoY+97tq140VAACEOA== # Create contract GitHubToken - from: '0x1081108d14493ead0d4071cc757688ed7b111c32' @@ -15,9 +24,9 @@ name: GitHubToken dir: contracts/ sources: - - BasicCoin.sol + - AbtractToken.sol - GithubToken.sol - - LockableCoin.sol + - CollaborationToken.sol - Token.sol - lib/oraclizeAPI_0.4.sol args: @@ -44,7 +53,7 @@ # Call method claim(string) - from: '0x1081108d14493ead0d4071cc757688ed7b111c32' - to: '0x56ba765b4da244fea35dd74d406220cb2703e478' + to: '0xcb69fe2674a9533ac30acf7a0a2a736f93f67fe1' value: '0x16345785d8a0000' call: claim(string) args: @@ -52,7 +61,7 @@ #transfer 101 eth - from: '0x1081108d14493ead0d4071cc757688ed7b111c32' - to: '0x56ba765b4da244fea35dd74d406220cb2703e478' + to: '0xcb69fe2674a9533ac30acf7a0a2a736f93f67fe1' value: '0x579a814e10a740000' data: null diff --git a/scenarios/Scenario1.yaml b/scenarios/Scenario1.yaml new file mode 100644 index 0000000..7c5a006 --- /dev/null +++ b/scenarios/Scenario1.yaml @@ -0,0 +1,14 @@ +# +# Scenario1 +# +# Created on: 06/03/2017 09:44:46 +# + +# Call method setAPICredentials(string,string) +- from: '0x1081108d14493ead0d4071cc757688ed7b111c32' + to: '0x838ef69e5948e423db15757059d538b5bcaf659e' + value: '0x0' + call: 'setAPICredentials(string,string)' + args: + - BLX/GHYsFjUNDKfRXSmJAGDrwzO3p1XFpK2DG9nwRHJ0wHMTA7K4wMj+eoKWc6HpkXnxwn/mC8GPsz3bbPnM6luWa7qLHdT94bQX4g19icuzgfm/4BkY6oK/EUhoE8IU34frpF4= + - BEMxXob2oNvdvo44KXhyBgou2xqr0Lits2wCy/OzrAIsfg5HO+GOEhdcEYrEByjhQosAJJX7uvuj7GVH65J8X7IFUFLrvWabWdTmPIEXwXoBGeU67z6SUtzOOgvAvFKixfl8pAWCDacJGZVQOoY+97tq140VAACEOA==