aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <herumi@nifty.com>2018-09-24 19:15:53 +0800
committerMITSUNARI Shigeo <herumi@nifty.com>2018-09-24 19:15:53 +0800
commit093a13335dd5390ad08a539c127c2b6663f41a88 (patch)
treea1c006985bb08af0e4614570d2cb4d09a6105826
parent76b13b05edab0bdf26b918286670bccf9013a0bf (diff)
downloadtangerine-mcl-093a13335dd5390ad08a539c127c2b6663f41a88.tar.gz
tangerine-mcl-093a13335dd5390ad08a539c127c2b6663f41a88.tar.zst
tangerine-mcl-093a13335dd5390ad08a539c127c2b6663f41a88.zip
add readHexStr, writeHexStr
-rw-r--r--include/mcl/conversion.hpp69
-rw-r--r--include/mcl/op.hpp3
-rw-r--r--test/conversion_test.cpp37
3 files changed, 97 insertions, 12 deletions
diff --git a/include/mcl/conversion.hpp b/include/mcl/conversion.hpp
index b5faa50..5ba7de0 100644
--- a/include/mcl/conversion.hpp
+++ b/include/mcl/conversion.hpp
@@ -131,23 +131,31 @@ inline uint32_t decToU32(const char *p, size_t size, bool *pb)
return x;
}
+inline bool hexCharToUint8(uint8_t *v, char _c)
+{
+ uint32_t c = uint8_t(_c); // cast is necessary
+ if (c - '0' <= '9' - '0') {
+ c = c - '0';
+ } else if (c - 'a' <= 'f' - 'a') {
+ c = (c - 'a') + 10;
+ } else if (c - 'A' <= 'F' - 'A') {
+ c = (c - 'A') + 10;
+ } else {
+ return false;
+ }
+ *v = c;
+ return true;
+}
+
template<class UT>
bool hexToUint(UT *px, const char *p, size_t size)
{
assert(0 < size && size <= sizeof(UT) * 2);
UT x = 0;
for (size_t i = 0; i < size; i++) {
- UT c = static_cast<uint8_t>(p[i]);
- if (c - 'A' <= 'F' - 'A') {
- c = (c - 'A') + 10;
- } else if (c - 'a' <= 'f' - 'a') {
- c = (c - 'a') + 10;
- } else if (c - '0' <= '9' - '0') {
- c = c - '0';
- } else {
- return false;
- }
- x = x * 16 + c;
+ uint8_t v;
+ if (!hexCharToUint8(&v, p[i])) return false;
+ x = x * 16 + v;
}
*px = x;
return true;
@@ -438,4 +446,43 @@ size_t strToArray(bool *pIsMinus, UT *x, size_t xN, const char *buf, size_t bufS
}
}
+/*
+ convert src[0, n) to (n * 2) byte hex string and write it to os
+ return true if success else flase
+*/
+template<class OutputStream>
+bool writeHexStr(OutputStream& os, const void *src, size_t n)
+{
+ bool b;
+ const uint8_t *p = (const uint8_t *)src;
+ for (size_t i = 0; i < n; i++) {
+ char hex[2];
+ cybozu::itohex(hex, sizeof(hex), p[i], false);
+ cybozu::write(&b, os, hex, sizeof(hex));
+ if (!b) return false;
+ }
+ return true;
+}
+/*
+ read hex string from is and convert it to byte array
+ return written buffer size
+*/
+template<class InputStream>
+inline size_t readHexStr(void *buf, size_t n, InputStream& is)
+{
+ bool b;
+ uint8_t *dst = (uint8_t *)buf;
+ for (size_t i = 0; i < n; i++) {
+ uint8_t L, H;
+ char c[2];
+ if (cybozu::readSome(c, sizeof(c), is) != sizeof(c)) return i;
+ b = local::hexCharToUint8(&H, c[0]);
+ if (!b) return i;
+ b = local::hexCharToUint8(&L, c[1]);
+ if (!b) return i;
+ dst[i] = (H << 4) | L;
+ }
+ return n;
+}
+
} } // mcl::fp
diff --git a/include/mcl/op.hpp b/include/mcl/op.hpp
index b0581bf..56c1389 100644
--- a/include/mcl/op.hpp
+++ b/include/mcl/op.hpp
@@ -101,7 +101,8 @@ enum IoMode {
IoEcCompY = 256, // 1-bit y representation of elliptic curve
IoSerialize = 512, // use MBS for 1-bit y
IoFixedSizeByteSeq = IoSerialize, // obsolete
- IoEcProj = 1024 // projective or jacobi coordinate
+ IoEcProj = 1024, // projective or jacobi coordinate
+ IoSerializeHexStr = 2048 // printable hex string
};
namespace fp {
diff --git a/test/conversion_test.cpp b/test/conversion_test.cpp
index 0f39907..06f31af 100644
--- a/test/conversion_test.cpp
+++ b/test/conversion_test.cpp
@@ -55,3 +55,40 @@ CYBOZU_TEST_AUTO(arrayToDec)
CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn);
}
}
+
+CYBOZU_TEST_AUTO(writeHexStr)
+{
+ const char *hex1tbl = "0123456789abcdef";
+ const char *hex2tbl = "0123456789ABCDEF";
+ for (size_t i = 0; i < 16; i++) {
+ uint8_t v = 0xff;
+ CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex1tbl[i]));
+ CYBOZU_TEST_EQUAL(v, i);
+ CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex2tbl[i]));
+ CYBOZU_TEST_EQUAL(v, i);
+ }
+ const struct Tbl {
+ const char *bin;
+ size_t n;
+ const char *hex;
+ } tbl[] = {
+ { "", 0, "" },
+ { "\x12\x34\xab", 3, "1234ab" },
+ { "\xff\xfc\x00\x12", 4, "fffc0012" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[32];
+ cybozu::MemoryOutputStream os(buf, sizeof(buf));
+ const char *bin = tbl[i].bin;
+ const char *hex = tbl[i].hex;
+ size_t n = tbl[i].n;
+ CYBOZU_TEST_ASSERT(mcl::fp::writeHexStr(os, bin, n));
+ CYBOZU_TEST_EQUAL(os.getPos(), n * 2);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, hex, n * 2);
+
+ cybozu::MemoryInputStream is(hex, n * 2);
+ size_t w = mcl::fp::readHexStr(buf, n, is);
+ CYBOZU_TEST_EQUAL(w, n);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, bin, n);
+ }
+}