Point::steg_encode was leaving the 24 high bits of the buffer as zero. It also ignored the size parameter. The size parameter has now been removed, the zeros fixed and a test added to make sure that it is fixed. Per https://github.com/MystenLabs/ed25519-unsafe-libs, deprecate eddsa signing with separate pubkey and privkey input. Instead decaf_ed*_keypair_signmaster
@@ -43,7 +43,7 @@ def fillin(template,data): | |||||
ret = "" | ret = "" | ||||
while True: | while True: | ||||
dollars = template.find("$(",position) | dollars = template.find("$(",position) | ||||
if dollars is -1: return ret + template[position:] | |||||
if dollars == -1: return ret + template[position:] | |||||
ret += template[position:dollars] | ret += template[position:dollars] | ||||
position = dollars + 2 | position = dollars + 2 | ||||
parens = 1 | parens = 1 | ||||
@@ -45,8 +45,8 @@ $("DECAF_API_VIS extern const uint8_t * const DECAF_ED" + gf_shortname + "_NO_CO | |||||
#define $(C_NS)_EDDSA_DECODE_RATIO ($(cofactor) / $(eddsa_encode_ratio)) | #define $(C_NS)_EDDSA_DECODE_RATIO ($(cofactor) / $(eddsa_encode_ratio)) | ||||
#ifndef DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED | #ifndef DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED | ||||
/** If 1, add deprecation attribute to non-keypair API functions. For now, deprecate in Doxygen only. */ | |||||
#define DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED 0 | |||||
/** If 1, add deprecation attribute to non-keypair API functions. Now deprecated. */ | |||||
#define DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED 1 | |||||
#endif | #endif | ||||
/** @cond internal */ | /** @cond internal */ | ||||
@@ -551,12 +551,11 @@ public: | |||||
} | } | ||||
/** Steganographically encode this */ | /** Steganographically encode this */ | ||||
inline SecureBuffer steg_encode(Rng &rng, size_t size=STEG_BYTES) const /*throw(std::bad_alloc, LengthException)*/ { | |||||
if (size <= HASH_BYTES + 4 || size > 2*HASH_BYTES) throw LengthException(); | |||||
inline SecureBuffer steg_encode(Rng &rng) const /*throw(std::bad_alloc, LengthException)*/ { | |||||
SecureBuffer out(STEG_BYTES); | SecureBuffer out(STEG_BYTES); | ||||
decaf_error_t done; | decaf_error_t done; | ||||
do { | do { | ||||
rng.read(Buffer(out).slice(HASH_BYTES-4,STEG_BYTES-HASH_BYTES+1)); | |||||
rng.read(Buffer(out).slice(HASH_BYTES-4,STEG_BYTES-HASH_BYTES+4)); | |||||
uint32_t hint = 0; | uint32_t hint = 0; | ||||
for (int i=0; i<4; i++) { hint |= uint32_t(out[HASH_BYTES-4+i])<<(8*i); } | for (int i=0; i<4; i++) { hint |= uint32_t(out[HASH_BYTES-4+i])<<(8*i); } | ||||
done = invert_elligator(out, hint); | done = invert_elligator(out, hint); | ||||
@@ -72,8 +72,8 @@ static void print(const char *name, const Scalar &x) { | |||||
static void hexprint(const char *name, const SecureBuffer &buffer) { | static void hexprint(const char *name, const SecureBuffer &buffer) { | ||||
printf(" %s = 0x", name); | printf(" %s = 0x", name); | ||||
for (auto i = buffer.rbegin(); i!= buffer.rend(); ++i) { | |||||
printf("%02x", *i); | |||||
for (int i=buffer.size()-1; i>=0; i--) { | |||||
printf("%02x", buffer[i]); | |||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
@@ -292,7 +292,13 @@ static void test_elligator() { | |||||
} | } | ||||
Point t(rng); | Point t(rng); | ||||
point_check(test,t,t,t,0,0,t,Point::from_hash(t.steg_encode(rng)),"steg round-trip"); | |||||
SecureBuffer bsteg = t.steg_encode(rng); | |||||
if (bsteg[Point::STEG_BYTES-1] == 0 && bsteg[Point::STEG_BYTES-2] == 0 && bsteg[Point::STEG_BYTES-3] == 0) { | |||||
test.fail(); | |||||
printf(" Steg is nonuniform (probability of false failure = 2^-24)\n"); | |||||
hexprint(" steg buffer:", bsteg); | |||||
} | |||||
point_check(test,t,t,t,0,0,t,Point::from_hash(bsteg),"steg round-trip"); | |||||
FixedArrayBuffer<Point::HASH_BYTES> b3(rng), b4(b3); | FixedArrayBuffer<Point::HASH_BYTES> b3(rng), b4(b3); | ||||
t = Point::from_hash(b3); | t = Point::from_hash(b3); | ||||