Coder Social home page Coder Social logo

noknow-python's Introduction

NoKnow

Zero-Knowledge Proof implementation in pure python

Experimental
Built with ❤︎ by Austin Archer :)

Table of Contents

Credits

This is a slightly modified implementation of Schnorr's protocol that utilizes a state seed. The proofs used are rather complex in nature, but I will do my best to explain its functionality, but please refer to the research papers on which this implementation is based as it does a far more complete job with explanation than I.

Elliptic Curve Based Zero Knowledge Proofs and Their Applicability on Resource Constrained Devices by Ioannis Chatzigiannakis, Apostolos Pyrgelis, Paul G. Spirakis, and Yannis C. Stamatiou

Purpose

Zero-Knowledge Proofs are undoubtedly the future of authentication security within various IT and application development industrires. The ability to verify the veracity of a claim (ex: proving that you know a secret password), without divulging any information about the claim itself (ex: passwords or hashes), allows for servers to guarantee secure AAA operations (authentication, authorization, and accounting) without exposing private information. NoKnow is an implementation of a Non-Interactive Zero-Knowledge Proof protocol specifically designed for verifying text-based secrets, which is ideal for passwords or other authentication means.

How It Works

The fundamental problem on which this protocol is based is the Elliptic Curve Discrete Logarithm Problem.

With this principle in mind, knowing a private variable, n, is all that is required to produce the proper point. The first thing to do is generate a signature. This signature is produced by multiplying a known value, such as the hashed result of a password, by the elliptic curve's generator point:

Now that we have produced this signature, S, which can be represented as an (x, y) pair, we can publish this signature publicly so that subsequent messages can be proven to have been produced by the same key that produced the signature, while ensuring that the signature itself reveals nothing about the data used to produce it.

One of my main goals for developing this library was producing a secure and effective method of Zero-Knowledge authentication. Because messages can be verified against a signature, one method of authentication is for the verifier (server) to produce a random message (called a token, t), and send it to the user with a request for them to produce a proof with the provided token that can be verified against their public signature. This ensures that a single proof cannot be re-used by a malicious actor in future authentication attempts. Any proof generated will always be valid against a particular signature, but checking the value of the signed data against what the server expects will ensure, with a large enough random token, it is extremely unlikely that there will ever be a request that provides the same random token. Additionally, another method could be to use a JWT with a short expiration, e.g. 10 seconds, whos validity is checked before processing the proof. However, in this example, I will choose a static random token, "MyRandomToken".

Ultimately, this comes down to the fact that some of these values cancel out arithmetically during the proof, so they are simply not needed by the prover. First, let's look at some basic principles of point multiplication with elliptic curves:

During the validation project, what is ultimately checked is a hash, namely:

Since both t and salt are public pieces of information, what is actually important is the specific point that is generated. What we need to do is prove:

There we go! We have demonstrated that the point R can be demonstrated to be able to be derived from c and M without knowing the discriminators of S (k), M (m), or R (r). And since knowledge of all of these are required to create the proof, but their values are not transmitted during proving, the zero knowledge proof is complete.=---=9

API

The noknow Python API is meant to be simple and intuitive:

Core Components

noknow.core.ZKParameters:

The parameters used to initialize the Zero-Knowledge crypto system.

class ZKParameters(NamedTuple):
    """
    Parameters used to construct a ZK proof state using an curve and a random salt
    """
    alg: str                    # Hashing algorithm name
    curve: str                  # Standard Elliptic Curve name to use
    s: int                      # Random salt for the state

noknow.core.ZKSignature:

A crytographic, zero-knowledge signature that can be used to verify future messages.

class ZKSignature(NamedTuple):
    """
    Cryptographic public signature used to verify future messages
    """
    params: ZKParameters        # Reference ZK Parameters
    signature: int              # The public key derived from your original secret

noknow.core.ZKProof:

A cryptograpgic proof that can be verified against a signature.

class ZKProof(NamedTuple):
    """
    Non-deterministic cryptographic zero-knowledge proof that can be verified to ensure the
    private key used to create the proof is the same key used to generate the signature
    """
    params: ZKParameters        # Reference ZK Parameters
    c: int                      # The hash of the signed data and random point, R
    m: int                      # The offset from the secret `r` (`R=r*g`) from c * Hash(secret)

noknow.core.ZKData

Wrapper that contains a proof and the necessary data to validate the proof against a signature.

class ZKData(NamedTuple):
    """
    Wrapper to contain data and a signed proof using the data
    """
    data: Union[str, bytes, int]
    proof: ZKProof

ZK

The ZK class is the central component of NoKnow and its state (defined by ZKParameters) should be inherently known to both the Client (Prover) and Server (Verifier).

instance methods

Method Parameters Role Purpose
create_signature secret: Union[str, bytes] Prover Create a cryptographic signature derived from the value secret to be generated during initial registration and stored for subsequent challenge proofs
sign secret: Union[str, bytes]
data: Union[str, bytes, int]
Prover Create a ZKData object using the secret and any additional data
verify challenge: Union[ZKData, ZKProof]
signature: ZKSignature
data: Optional[Union[str, bytes, int]]
Verifier Verify the user-provided challenge against the stored signature and randomly generated token to verify the validity of the challenge

Install

NoKnow is available from PyPi! Simply run:

pip install -U noknow

Example Usage

TODO: Include example usage

Example 1

"""
Extremely simple example of NoKnow ZK Proof implementation
"""
from getpass import getpass
from noknow.core import ZK, ZKSignature, ZKParameters, ZKData, ZKProof
from queue import Queue
from threading import Thread


def client(iq: Queue, oq: Queue):
    client_zk = ZK.new(curve_name="secp256k1", hash_alg="sha3_256")

    # Create signature and send to server
    signature = client_zk.create_signature(getpass("Enter Password: "))
    oq.put(signature.dump())

    # Receive the token from the server
    token = iq.get()

    # Create a proof that signs the provided token and sends to server
    proof = client_zk.sign(getpass("Enter Password Again: "), token).dump()

    # Send the token and proof to the server
    oq.put(proof)

    # Wait for server response!
    print("Success!" if iq.get() else "Failure!")


def server(iq: Queue, oq: Queue):
    # Set up server component
    server_password = "SecretServerPassword"
    server_zk = ZK.new(curve_name="secp384r1", hash_alg="sha3_512")
    server_signature: ZKSignature = server_zk.create_signature("SecureServerPassword")

    # Load the received signature from the Client
    sig = iq.get()
    client_signature = ZKSignature.load(sig)
    client_zk = ZK(client_signature.params)

    # Create a signed token and send to the client
    token = server_zk.sign("SecureServerPassword", client_zk.token())
    oq.put(token.dump(separator=":"))

    # Get the token from the client
    proof = ZKData.load(iq.get())
    token = ZKData.load(proof.data, ":")

    # In this example, the server signs the token so it can be sure it has not been modified
    if not server_zk.verify(token, server_signature):
        oq.put(False)
    else:
        oq.put(client_zk.verify(proof, client_signature, data=token))


def main():
    q1, q2 = Queue(), Queue()
    threads = [
        Thread(target=client, args=(q1, q2)),
        Thread(target=server, args=(q2, q1)),
    ]
    for func in [Thread.start, Thread.join]:
        for thread in threads:
            func(thread)


if __name__ == "__main__":
    main()

noknow-python's People

Contributors

goodieshq avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

noknow-python's Issues

#question

assuming you get the value of the tokens, signatures , proofs, ZK instances for the client and the server. Would it be possible to get the "key" that it uses to generate all? From what I understood how it would work, I think not since this protocol allows that, right? prove that something is known without showing it. is that so?

ZKSignature.loads doesn't work

Heya,

Trying to elaborate on the example. There is no function called "loads" on data.py or core.py. The ZKSignature class also does not have the load function, E.g: ZKData.load(iq.get()) so im wondering if you meant: ZKData.from_json(iq.get())? But this then also brings encoding issues.

Mel

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.