Browse Source

add crypto.hxx that doesnt work yet

master
Mike Hamburg 9 years ago
parent
commit
2162dbe78d
1 changed files with 178 additions and 0 deletions
  1. +178
    -0
      src/public_include/decaf/crypto.hxx

+ 178
- 0
src/public_include/decaf/crypto.hxx View File

@@ -0,0 +1,178 @@
/**
* @file decaf/crypto.hxx
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* @brief Example cryptography using Decaf
*/
#ifndef __DECAF_CRYPTO_HXX__
#define __DECAF_CRYPTO_HXX__ 1

#include <decaf.hxx>
#include <decaf/shake.hxx>

/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#else
#define NOEXCEPT throw()
#endif
/** @endcond */

/* TODO: decide on copy vs reference */

namespace decaf {
template <typename Group> class PrivateKey;

/** @brief A public key using a particular EC group */
template <typename Group> class PublicKey {
private:
/** @cond internal */
friend class PrivateKey<Group>;
//const typename Group::Point p;
const FixedArrayBuffer<Group::Point::SER_BYTES> ser;
static const size_t CHALLENGE_BYTES = Group::Scalar::SER_BYTES;
/** @endcond */

public:
/** SHAKE instance size for sigs etc */
static const size_t SHAKE_BITS = 256;
/** Size of a signature */
static const size_t SIG_BYTES = Group::Point::SER_BYTES + Group::Scalar::SER_BYTES;
/** @brief Return a pointer to the serialized version of the point. */
inline operator FixedBlock<Group::Point::SER_BYTES>() const NOEXCEPT {
return ser;
}
/** @brief Set the public key to a point */
inline explicit PublicKey(const typename Group::Point &p) NOEXCEPT : ser(SecureBuffer(p)) {}
/** @brief Get the private key for a given public key */
inline explicit PublicKey(const PrivateKey<Group> &priv) NOEXCEPT;
/** @brief Read a private key from a string*/
inline explicit PublicKey(const FixedBlock<Group::Point::SER_BYTES> b) NOEXCEPT : ser(b) {}
/** @brief Return the corresponding EC point */
inline typename Group::Point point() const throw(CryptoException) {
return typename Group::Point(ser);
}
/** @brief Verify a sig. TODO: nothrow version? */
inline void verify_shake(const SHAKE<SHAKE_BITS> &ctx_, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) {
SHAKE<SHAKE_BITS> ctx(ctx_);
ctx << ser << sig.slice(0,Group::Point::SER_BYTES);
FixedBuffer<CHALLENGE_BYTES> challenge(ctx.output(CHALLENGE_BYTES));
challenge.debug_print("ch ver ");
const typename Group::Point combo = point().non_secret_combo_with_base(
challenge,
sig.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES)
);
if (combo != typename Group::Point(sig.slice(0,Group::Point::SER_BYTES)))
throw CryptoException();
}

/** @brief Sign from a message. */
inline void verify(const Block &message, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) {
SHAKE<SHAKE_BITS> ctx;
ctx << message;
verify_shake(ctx,sig);
}
};

/** @brief A private key using a particular EC group */
template <typename Group> class PrivateKey {
public:
/** Size of associated symmetric key */
static const size_t SYM_BYTES = 32;
/** SHAKE instance size for sigs etc */
static const size_t SHAKE_BITS = PublicKey<Group>::SHAKE_BITS;
private:
/** @cond internal */
static const size_t SCALAR_HASH_BYTES = Group::Scalar::SER_BYTES + 8;
friend class PublicKey<Group>;
const FixedArrayBuffer<SYM_BYTES> sym;
const typename Group::Scalar scalar;
const PublicKey<Group> pub_;
/** @endcond */
public:
/** @brief Construct at random */
inline PrivateKey(Rng &r) :
sym(r),
scalar(SHAKE<SHAKE_BITS>::hash(sym, SCALAR_HASH_BYTES)),
pub_(SecureBuffer(Group::Precomputed::base() * scalar)) {}
/** @brief Construct from buffer */
inline PrivateKey(const FixedBlock<SYM_BYTES> &sym_) :
sym(sym_),
scalar(SHAKE<SHAKE_BITS>::hash(sym, SCALAR_HASH_BYTES)),
pub_(SecureBuffer(Group::Precomputed::Base * scalar)) {}
/** @brief Compressed representation */
inline const FixedBlock<SYM_BYTES> &ser_compressed() const NOEXCEPT {
return sym;
}
/** @brief Uncompressed representation */
inline SecureBuffer ser_uncompressed() const throw(std::bad_alloc) {
SecureBuffer b(SYM_BYTES + Group::Scalar::SER_BYTES + Group::Point::SER_BYTES);
b.slice(0,SYM_BYTES).assign(sym);
b.slice(SYM_BYTES,Group::Scalar::SER_BYTES).assign(scalar);
b.slice(SYM_BYTES+Group::Scalar::SER_BYTES,Group::Point::SER_BYTES).assign(pub_.ser);
return b;
}
/** @brief Sign from a SHAKE context. TODO: double check random oracle eval of this; destructive version? */
inline SecureBuffer sign_shake(const SHAKE<SHAKE_BITS> &ctx_) NOEXCEPT {
SHAKE<SHAKE_BITS> ctx(ctx_);
ctx << sym << "decaf_255_sign_shake";
typename Group::Scalar nonce(ctx.output(SCALAR_HASH_BYTES));
SecureBuffer g_nonce(Group::Precomputed::base() * nonce); /* FIXME: make output fixed size, avoid std::bad_alloc */
ctx = ctx_;
ctx << pub_.ser << g_nonce;
FixedBuffer<PublicKey<Group>::CHALLENGE_BYTES> challenge(ctx.output(PublicKey<Group>::CHALLENGE_BYTES));
challenge.debug_print("ch sign");
SecureBuffer response(nonce - scalar * challenge);
SecureBuffer ret(PublicKey<Group>::SIG_BYTES);
ret.slice(0,Group::Point::SER_BYTES).assign(g_nonce);
ret.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES).assign(response);
return ret;
}
/** @brief Sign from a message. */
inline SecureBuffer sign(const Block &message) {
SHAKE<SHAKE_BITS> ctx;
ctx << message;
return sign_shake(ctx);
}
/** @brief Get the corresponding public key */
inline const PublicKey<Group> &pub() const { return pub_; }
};

/** @cond internal */
template <typename Group>
inline PublicKey<Group>::PublicKey(
const PrivateKey<Group> &priv
) NOEXCEPT : ser(priv.pub_.ser){}
/** @endcond */

#undef NOEXCEPT
} /* namespace decaf */

#endif /* __DECAF_CRYPTO_HXX__ */


Loading…
Cancel
Save