@@ -0,0 +1,2 @@ | |||||
src/generator/curve_data.pyc | |||||
src/generator/__pycache__/ |
@@ -10,13 +10,16 @@ project(DECAF VERSION 1.0 LANGUAGES C CXX) | |||||
set(DECAF_SO_VERSION "0") | set(DECAF_SO_VERSION "0") | ||||
find_package( PythonInterp 2.7 REQUIRED ) | |||||
find_package(PythonInterp 3 REQUIRED) | |||||
option(ENABLE_SHARED "Build shared library." ON) | option(ENABLE_SHARED "Build shared library." ON) | ||||
option(ENABLE_STATIC "Build static library." ON) | option(ENABLE_STATIC "Build static library." ON) | ||||
option(ENABLE_STRICT "Build with strict compile options." YES) | option(ENABLE_STRICT "Build with strict compile options." YES) | ||||
option(ENABLE_TESTS "Enable compilation of tests." OFF) | option(ENABLE_TESTS "Enable compilation of tests." OFF) | ||||
option(GENERATED_SOURCE_PATH "Where the generated source code is stored, default in the building tree" OFF) | option(GENERATED_SOURCE_PATH "Where the generated source code is stored, default in the building tree" OFF) | ||||
if (CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") | |||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib") | |||||
endif() | |||||
if (GENERATED_SOURCE_PATH) | if (GENERATED_SOURCE_PATH) | ||||
set(GSOURCE_PATH ${GENERATED_SOURCE_PATH}) | set(GSOURCE_PATH ${GENERATED_SOURCE_PATH}) | ||||
@@ -46,12 +49,12 @@ set(STRICT_OPTIONS_C ) | |||||
set(STRICT_OPTIONS_CXX ) | set(STRICT_OPTIONS_CXX ) | ||||
if(MSVC) | if(MSVC) | ||||
if(ENABLE_STRICT) | if(ENABLE_STRICT) | ||||
set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} /WX") | |||||
set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} /WX /Zc:__cplusplus") | |||||
endif() | endif() | ||||
else() | else() | ||||
set(STRICT_OPTIONS_CXX "${STRICT_OPTIONS_CXX} -std=c++11 -O2") | |||||
set(STRICT_OPTIONS_CXX "${STRICT_OPTIONS_CXX} -std=c++14 -O2") | |||||
set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wall -Wuninitialized -Wno-deprecated-declarations -Wno-missing-field-initializers") | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wall -Wuninitialized -Wno-deprecated-declarations -Wno-missing-field-initializers") | ||||
set(STRICT_OPTIONS_C "${STRICT_OPTIONS_C} -std=c99 -O2 -Wstrict-prototypes -Wno-error=strict-prototypes -fvisibility=hidden") | |||||
set(STRICT_OPTIONS_C "${STRICT_OPTIONS_C} -std=c99 -O2 -Wstrict-prototypes -Wno-error=strict-prototypes -fvisibility=hidden -Wno-error=implicit-function-declaration -Wno-error=attributes") | |||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang") | if(CMAKE_C_COMPILER_ID MATCHES "Clang") | ||||
set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wno-error=unknown-warning-option -Qunused-arguments -Wno-tautological-compare") | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wno-error=unknown-warning-option -Qunused-arguments -Wno-tautological-compare") | ||||
set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wno-unused-function -Wno-pass-failed") | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wno-unused-function -Wno-pass-failed") | ||||
@@ -36,12 +36,18 @@ set(TARGET_ARCH_DIR_P25519 arch_32) | |||||
# availables: arch_32, arch_arm_32, arch_neon, arch_ref64, arch_x86_64 | # availables: arch_32, arch_arm_32, arch_neon, arch_ref64, arch_x86_64 | ||||
set(TARGET_ARCH_DIR_P448 arch_32) | set(TARGET_ARCH_DIR_P448 arch_32) | ||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") # x86_64 | |||||
if(MSVC)# On MSVC Windows, Processor is always AMD64 on both platforms (x86/x64) | |||||
set(MSVC_ARCH ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID})# ${MSVC_ARCH} MATCHES "X64" | |||||
else() | |||||
set(MSVC_ARCH ${CMAKE_SYSTEM_PROCESSOR})# just to have a value | |||||
endif() | |||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" AND NOT MSVC)#Decaf doesn't support 64bits on MSVC yet | |||||
message("Target architecture is x86_64") | message("Target architecture is x86_64") | ||||
set(TARGET_ARCH_DIR arch_x86_64) | set(TARGET_ARCH_DIR arch_x86_64) | ||||
set(TARGET_ARCH_DIR_P25519 arch_x86_64) | set(TARGET_ARCH_DIR_P25519 arch_x86_64) | ||||
set(TARGET_ARCH_DIR_P448 arch_x86_64) | set(TARGET_ARCH_DIR_P448 arch_x86_64) | ||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arch64") # shall be arm64 bits, stick to ref64 | |||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arch64") # shall be arm64 bits, stick to ref64. | |||||
message("Target architecture is 64 bits general purpose(arm64 shall use this)") | message("Target architecture is 64 bits general purpose(arm64 shall use this)") | ||||
set(TARGET_ARCH_DIR arch_ref64) | set(TARGET_ARCH_DIR arch_ref64) | ||||
set(TARGET_ARCH_DIR_P25519 arch_ref64) | set(TARGET_ARCH_DIR_P25519 arch_ref64) | ||||
@@ -75,13 +75,13 @@ add_custom_command( | |||||
COMMENT "Generating code for include/decaf/ed255.hxx" | COMMENT "Generating code for include/decaf/ed255.hxx" | ||||
) | ) | ||||
add_custom_target(generatorCurve25519AndGenTablesCommon DEPENDS | |||||
add_custom_target(genC25519nTab DEPENDS | |||||
${GSOURCE_PATH}/c/curve25519/decaf.c | ${GSOURCE_PATH}/c/curve25519/decaf.c | ||||
${GSOURCE_PATH}/c/curve25519/scalar.c | ${GSOURCE_PATH}/c/curve25519/scalar.c | ||||
) | ) | ||||
add_custom_target(generatorCurve25519 DEPENDS | add_custom_target(generatorCurve25519 DEPENDS | ||||
generatorP25519 | generatorP25519 | ||||
generatorCurve25519AndGenTablesCommon | |||||
genC25519nTab | |||||
${GSOURCE_PATH}/c/curve25519/elligator.c | ${GSOURCE_PATH}/c/curve25519/elligator.c | ||||
${GSOURCE_PATH}/c/curve25519/eddsa.c | ${GSOURCE_PATH}/c/curve25519/eddsa.c | ||||
${GSOURCE_PATH}/include/decaf/point_255.hxx | ${GSOURCE_PATH}/include/decaf/point_255.hxx | ||||
@@ -98,7 +98,7 @@ add_executable(decaf_gen_tables_curve25519 EXCLUDE_FROM_ALL ${GSOURCE_PATH}/c/cu | |||||
${GSOURCE_PATH}/c/curve25519/scalar.c | ${GSOURCE_PATH}/c/curve25519/scalar.c | ||||
${PROJECT_SOURCE_DIR}/src/utils.c | ${PROJECT_SOURCE_DIR}/src/utils.c | ||||
$<TARGET_OBJECTS:p25519>) | $<TARGET_OBJECTS:p25519>) | ||||
add_dependencies(decaf_gen_tables_curve25519 generatorCurve25519AndGenTablesCommon) | |||||
add_dependencies(decaf_gen_tables_curve25519 genC25519nTab) | |||||
add_custom_target(decaf_tables_curve25519 | add_custom_target(decaf_tables_curve25519 | ||||
COMMAND decaf_gen_tables_curve25519 > ${PROJECT_SOURCE_DIR}/src/curve25519/decaf_tables.c | COMMAND decaf_gen_tables_curve25519 > ${PROJECT_SOURCE_DIR}/src/curve25519/decaf_tables.c | ||||
@@ -82,13 +82,13 @@ add_custom_command( | |||||
COMMENT "Generating code for include/decaf/ed448.hxx" | COMMENT "Generating code for include/decaf/ed448.hxx" | ||||
) | ) | ||||
add_custom_target(generatorEd448AndGenTablesCommon DEPENDS | |||||
add_custom_target(genEd448nTab DEPENDS | |||||
${GSOURCE_PATH}/c/ed448goldilocks/scalar.c | ${GSOURCE_PATH}/c/ed448goldilocks/scalar.c | ||||
${GSOURCE_PATH}/c/ed448goldilocks/decaf.c | ${GSOURCE_PATH}/c/ed448goldilocks/decaf.c | ||||
) | ) | ||||
add_custom_target(generatorEd448goldilocks DEPENDS | add_custom_target(generatorEd448goldilocks DEPENDS | ||||
generatorP448 | generatorP448 | ||||
generatorEd448AndGenTablesCommon | |||||
genEd448nTab | |||||
${GSOURCE_PATH}/c/ed448goldilocks/elligator.c | ${GSOURCE_PATH}/c/ed448goldilocks/elligator.c | ||||
${GSOURCE_PATH}/c/ed448goldilocks/eddsa.c | ${GSOURCE_PATH}/c/ed448goldilocks/eddsa.c | ||||
${GSOURCE_PATH}/include/decaf/point_448.hxx | ${GSOURCE_PATH}/include/decaf/point_448.hxx | ||||
@@ -105,7 +105,7 @@ add_executable(decaf_gen_tables_ed448goldilocks EXCLUDE_FROM_ALL ${GSOURCE_PATH} | |||||
${GSOURCE_PATH}/c/ed448goldilocks/scalar.c | ${GSOURCE_PATH}/c/ed448goldilocks/scalar.c | ||||
${PROJECT_SOURCE_DIR}/src/utils.c | ${PROJECT_SOURCE_DIR}/src/utils.c | ||||
$<TARGET_OBJECTS:p448>) | $<TARGET_OBJECTS:p448>) | ||||
add_dependencies(decaf_gen_tables_ed448goldilocks generatorEd448AndGenTablesCommon) | |||||
add_dependencies(decaf_gen_tables_ed448goldilocks genEd448nTab) | |||||
add_custom_target(decaf_tables_ed448goldilocks | add_custom_target(decaf_tables_ed448goldilocks | ||||
COMMAND decaf_gen_tables_ed448goldilocks > ${PROJECT_SOURCE_DIR}/src/ed448goldilocks/decaf_tables.c | COMMAND decaf_gen_tables_ed448goldilocks > ${PROJECT_SOURCE_DIR}/src/ed448goldilocks/decaf_tables.c | ||||
@@ -151,7 +151,7 @@ DECAF_INLINE mask_t bit_to_mask(uint8_t bit) { | |||||
br_set_to_mask(mask_t x) { | br_set_to_mask(mask_t x) { | ||||
return vdupq_n_u32(x); | return vdupq_n_u32(x); | ||||
} | } | ||||
#elif _WIN64 || __amd64__ || __X86_64__ || __aarch64__ | |||||
#elif __amd64__ || __X86_64__ || __aarch64__ /* || _WIN64 -> WIN64 does not support int128 so force the build on arch32 default so do not use this define for _WIN64*/ | |||||
#define VECTOR_ALIGNED __attribute__((aligned(8))) | #define VECTOR_ALIGNED __attribute__((aligned(8))) | ||||
typedef uint64_t big_register_t, uint64xn_t; | typedef uint64_t big_register_t, uint64xn_t; | ||||
@@ -130,7 +130,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size() | |||||
static_cast<uint8_t>(context.size()) | |||||
); | ); | ||||
return out; | return out; | ||||
} | } | ||||
@@ -147,7 +147,7 @@ public: | |||||
((const CRTP*)this)->keypair_, | ((const CRTP*)this)->keypair_, | ||||
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped, | (const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped, | ||||
ph.context_.data(), | ph.context_.data(), | ||||
ph.context_.size() | |||||
static_cast<uint8_t>(ph.context_.size()) | |||||
); | ); | ||||
return out; | return out; | ||||
} | } | ||||
@@ -266,7 +266,7 @@ public: | |||||
message.size(), | message.size(), | ||||
0, | 0, | ||||
context.data(), | context.data(), | ||||
context.size() | |||||
static_cast<uint8_t>(context.size()) | |||||
); | ); | ||||
} | } | ||||
@@ -319,7 +319,7 @@ public: | |||||
((const CRTP*)this)->pub_.data(), | ((const CRTP*)this)->pub_.data(), | ||||
(const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped, | (const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped, | ||||
ph.context_.data(), | ph.context_.data(), | ||||
ph.context_.size() | |||||
static_cast<uint8_t>(ph.context_.size()) | |||||
)) { | )) { | ||||
throw CryptoException(); | throw CryptoException(); | ||||
} | } | ||||
@@ -122,7 +122,14 @@ public: | |||||
/** Assign from signed int. */ | /** Assign from signed int. */ | ||||
inline Scalar& operator=(int64_t w) DECAF_NOEXCEPT { | inline Scalar& operator=(int64_t w) DECAF_NOEXCEPT { | ||||
#ifdef _MSC_VER | |||||
#pragma warning ( push) | |||||
#pragma warning ( disable : 4146) | |||||
#endif | |||||
Scalar t(-(uint64_t)INT_MIN); | Scalar t(-(uint64_t)INT_MIN); | ||||
#ifdef _MSC_VER | |||||
#pragma warning ( pop) | |||||
#endif | |||||
$(c_ns)_scalar_set_unsigned(s,(uint64_t)w - (uint64_t)INT_MIN); | $(c_ns)_scalar_set_unsigned(s,(uint64_t)w - (uint64_t)INT_MIN); | ||||
*this -= t; | *this -= t; | ||||
return *this; | return *this; | ||||
@@ -216,7 +216,7 @@ API_NS(scalar_eq) ( | |||||
static DECAF_INLINE void scalar_decode_short ( | static DECAF_INLINE void scalar_decode_short ( | ||||
scalar_t s, | scalar_t s, | ||||
const unsigned char *ser, | const unsigned char *ser, | ||||
unsigned int nbytes | |||||
size_t nbytes | |||||
) { | ) { | ||||
unsigned int i,j,k=0; | unsigned int i,j,k=0; | ||||
for (i=0; i<SCALAR_LIMBS; i++) { | for (i=0; i<SCALAR_LIMBS; i++) { | ||||
@@ -178,16 +178,22 @@ public: | |||||
/** Block from std::string */ | /** Block from std::string */ | ||||
inline Block(const std::string &s) : data_( | inline Block(const std::string &s) : data_( | ||||
#if __cplusplus >= 201103L | |||||
((unsigned char *)&(s)[0]) | |||||
#else | |||||
#if __cplusplus >= 201103L | |||||
((unsigned char *)(s.data())) | ((unsigned char *)(s.data())) | ||||
#endif | |||||
), size_(s.size()), zero_on_destroy_(false) {} | |||||
#else | |||||
((unsigned char *)&(s)[0]) | |||||
#endif | |||||
), size_(s.size()), zero_on_destroy_(false) {} | |||||
/** Block from std::vector */ | /** Block from std::vector */ | ||||
template<class alloc> inline Block(const std::vector<unsigned char,alloc> &s) | template<class alloc> inline Block(const std::vector<unsigned char,alloc> &s) | ||||
: data_(((unsigned char *)&(s)[0])), size_(s.size()), zero_on_destroy_(false) {} | |||||
: data_( | |||||
#if __cplusplus >= 201103L | |||||
((unsigned char *)(s.data())) | |||||
#else | |||||
((unsigned char *)&(s)[0]) | |||||
#endif | |||||
), size_(s.size()), zero_on_destroy_(false) {} | |||||
/** Get const data */ | /** Get const data */ | ||||
inline const unsigned char *data() const DECAF_NOEXCEPT { return data_; } | inline const unsigned char *data() const DECAF_NOEXCEPT { return data_; } | ||||
@@ -405,7 +411,11 @@ protected: | |||||
inline void clear() DECAF_NOEXCEPT { | inline void clear() DECAF_NOEXCEPT { | ||||
if (is_mine) { | if (is_mine) { | ||||
really_bzero(ours.mine, T::size()); | really_bzero(ours.mine, T::size()); | ||||
#ifdef _MSC_VER | |||||
_aligned_free(ours.mine); | |||||
#else | |||||
free(ours.mine); | free(ours.mine); | ||||
#endif // _MSC_VER | |||||
ours.yours = T::default_value(); | ours.yours = T::default_value(); | ||||
is_mine = false; | is_mine = false; | ||||
} | } | ||||
@@ -482,6 +492,11 @@ template<typename T, size_t alignment> | |||||
void SanitizingAllocator<T,alignment>::deallocate(T* p, size_t size) DECAF_NOEXCEPT { | void SanitizingAllocator<T,alignment>::deallocate(T* p, size_t size) DECAF_NOEXCEPT { | ||||
if (p==NULL) return; | if (p==NULL) return; | ||||
really_bzero(reinterpret_cast<void*>(p), size); | really_bzero(reinterpret_cast<void*>(p), size); | ||||
#ifdef _MSC_VER | |||||
if (alignment) | |||||
_aligned_free(reinterpret_cast<void*>(p)); | |||||
else | |||||
#endif // _MSC_VER | |||||
free(reinterpret_cast<void*>(p)); | free(reinterpret_cast<void*>(p)); | ||||
} | } | ||||
@@ -9,6 +9,18 @@ | |||||
* @warning The SpongeRNG code isn't stable. Future versions are likely to | * @warning The SpongeRNG code isn't stable. Future versions are likely to | ||||
* have different outputs. Of course, this only matters in deterministic mode. | * have different outputs. Of course, this only matters in deterministic mode. | ||||
*/ | */ | ||||
#if defined(_MSC_VER) | |||||
#define _CRT_RAND_S | |||||
#include <stdlib.h> | |||||
# include <io.h> | |||||
#include <BaseTsd.h> | |||||
#define open _open | |||||
#define read _read | |||||
#define close _close | |||||
typedef SSIZE_T ssize_t; | |||||
#else | |||||
# include <unistd.h> | |||||
#endif | |||||
#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ | #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ | ||||
#include <assert.h> | #include <assert.h> | ||||
@@ -22,16 +34,7 @@ | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#if defined(_MSC_VER) | |||||
# include <io.h> | |||||
#include <BaseTsd.h> | |||||
#define open _open | |||||
#define read _read | |||||
#define close _close | |||||
typedef SSIZE_T ssize_t; | |||||
#else | |||||
# include <unistd.h> | |||||
#endif | |||||
/** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */ | /** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */ | ||||
static void get_cpu_entropy(uint8_t *entropy, size_t len) { | static void get_cpu_entropy(uint8_t *entropy, size_t len) { | ||||
@@ -161,12 +164,35 @@ decaf_error_t decaf_spongerng_init_from_file ( | |||||
prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */ | prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */ | ||||
if (!len) return DECAF_FAILURE; | if (!len) return DECAF_FAILURE; | ||||
#if defined _MSC_VER | |||||
/* no /dev/urandom on windows, use rand_s instead */ | |||||
if (strcmp(file, "/dev/urandom") == 0) { | |||||
unsigned int r; | |||||
uint8_t buffer[sizeof(unsigned int)]; | |||||
errno_t err; | |||||
while (len) { | |||||
int i; | |||||
err = rand_s(&r); | |||||
if (err != 0) { | |||||
return DECAF_FAILURE; | |||||
} | |||||
for (i = 0; i < sizeof(unsigned int); i++) { | |||||
buffer[i] = (uint8_t)(r & 0xff); | |||||
r >>= 8; | |||||
} | |||||
size_t consumed = (len > sizeof(buffer)) ? sizeof(buffer) : len; | |||||
decaf_sha3_update(prng->sponge, buffer, consumed); | |||||
len -= consumed; | |||||
} | |||||
} else { | |||||
#endif /* _MSC_VER */ | |||||
int fd = open(file, O_RDONLY); | int fd = open(file, O_RDONLY); | ||||
if (fd < 0) return DECAF_FAILURE; | if (fd < 0) return DECAF_FAILURE; | ||||
uint8_t buffer[128]; | uint8_t buffer[128]; | ||||
while (len) { | while (len) { | ||||
ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len); | |||||
ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : (unsigned int)len); | |||||
if (red <= 0) { | if (red <= 0) { | ||||
close(fd); | close(fd); | ||||
return DECAF_FAILURE; | return DECAF_FAILURE; | ||||
@@ -175,6 +201,9 @@ decaf_error_t decaf_spongerng_init_from_file ( | |||||
len -= red; | len -= red; | ||||
}; | }; | ||||
close(fd); | close(fd); | ||||
#if defined _MSC_VER | |||||
} | |||||
#endif /* _MSC_VER */ | |||||
const uint8_t nope; | const uint8_t nope; | ||||
decaf_spongerng_stir(prng,&nope,0); | decaf_spongerng_stir(prng,&nope,0); | ||||
@@ -102,7 +102,7 @@ public: | |||||
if (strlen(s) < 25) printf("%*s",int(25-strlen(s)),""); | if (strlen(s) < 25) printf("%*s",int(25-strlen(s)),""); | ||||
fflush(stdout); | fflush(stdout); | ||||
i = j = 0; | i = j = 0; | ||||
ntests = NTESTS * factor; | |||||
ntests = static_cast<int>(NTESTS * factor); | |||||
nsamples = NSAMPLES; | nsamples = NSAMPLES; | ||||
begin = now(); | begin = now(); | ||||
tsc_begin = rdtsc(); | tsc_begin = rdtsc(); | ||||
@@ -13,6 +13,7 @@ | |||||
#include <io.h> | #include <io.h> | ||||
#include <BaseTsd.h> | #include <BaseTsd.h> | ||||
typedef SSIZE_T ssize_t; | typedef SSIZE_T ssize_t; | ||||
#define read _read | |||||
#else | #else | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#endif | #endif | ||||
@@ -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 (int i=buffer.size()-1; i>=0; i--) { | |||||
printf("%02x", buffer[i]); | |||||
for (auto i = buffer.rbegin(); i!= buffer.rend(); ++i) { | |||||
printf("%02x", *i); | |||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||