首页 > 解决方案 > HMAC-SHA512 的未定义行为每次都会给出不同的结果

问题描述

我想通过应用 HMAC(sha512,..) 从主密钥派生一个 (44') 强化私钥,但我不断得到不同的任意结果。奇怪的是第一次使用了相同的 hmac-sha512 函数,并通过从种子中派生主密钥给出了正确的结果,但第二次使用它来获取硬化私钥失败,我认为这与valgrind 作为 memcheck 的内存显示了几个错误。

这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/sha.h>
#include <openssl/hmac.h>


void GenerateMKey();
void CKDPrivate();


int main(int argc, char **argv)
{
    
    unsigned char seed[64]={0x67, 0xf9, 0x35, 0x60, 0x76, 0x1e, 0x20, 0x61, 0x7d, 0xe2,
                            0x6e, 0x0c, 0xb8, 0x4f, 0x72, 0x34, 0xaa, 0xf3, 0x73, 0xed,
                            0x2e, 0x66, 0x29, 0x5c, 0x3d, 0x73, 0x97, 0xe6, 0xd7, 0xeb,
                            0xe8, 0x82, 0xea, 0x39, 0x6d, 0x5d, 0x29, 0x38, 0x08, 0xb0,
                            0xde, 0xfd, 0x7e, 0xdd, 0x2b, 0xab, 0xd4, 0xc0, 0x91, 0xad,
                            0x94, 0x2e, 0x6a, 0x93, 0x51, 0xe6, 0xd0, 0x75, 0xa2, 0x9d,
                            0x4d, 0xf8, 0x72, 0xaf};
    unsigned char mkey[64];
    unsigned char ekey[64];
    //unsigned char n[4]={0x00,0x00,0x00,0x00};
    unsigned char h[4]={0x80,0x00,0x00,0x00};

    GenerateMKey(seed,mkey);
    for(int i=0; i<32; i++){ printf("%02x",mkey[i]);} printf("\n");
    CKDPrivate(mkey,ekey,h,44);
    for(int i=0; i<32; i++){ printf("%02x",ekey[i]);} printf("\n");


    return 0;
}

void GenerateMKey(unsigned char *s, unsigned char *m)
{

    char key[]="Bitcoin seed";

    HMAC(EVP_sha512(),key,strlen(key),s,64,m,0);

}


void CKDPrivate(unsigned char *m, unsigned char *e, unsigned char *x, int i)
{
    
    unsigned char c[32],d[37];
    d[0]=0;
    memcpy(d+1,m,32);
    x[3]=i;
    memcpy(d+33,x,4);
    //d[37]='\0';
    memcpy(c,m+32,32);
    HMAC(EVP_sha512(),c,32,d,64,e,0);
    
}

这是 Valgrind 的错误报告

@system:~$ valgrind --leak-check=full -v --show-leak-kinds=all --track-origins=yes CodeLite/build-Debug/bin/teset3
==187198== Memcheck, a memory error detector
==187198== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==187198== Using Valgrind-3.16.1-36d6727e1d-20200622X and LibVEX; rerun with -h for copyright info
==187198== Command: CodeLite/build-Debug/bin/teset3
==187198== 
--187198-- Valgrind options:
--187198--    --leak-check=full
--187198--    -v
--187198--    --show-leak-kinds=all
--187198--    --track-origins=yes
--187198-- Contents of /proc/version:
--187198--   Linux version 5.9.0-5-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-1) 10.2.1 20201207, GNU ld (GNU Binutils for Debian) 2.35.1) #1 SMP Debian 5.9.15-1 (2020-12-17)
--187198-- 
--187198-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-rdtscp-sse3-ssse3
--187198-- Page sizes: currently 4096, max supported 4096
--187198-- Valgrind library directory: /usr/lib/x86_64-linux-gnu/valgrind
--187198-- Reading syms from /home/soufiane/CodeLite/build-Debug/bin/teset3
--187198-- Reading syms from /lib/x86_64-linux-gnu/ld-2.31.so
--187198--   Considering /usr/lib/debug/.build-id/8c/8fb7a300a76834b3b719afc53d1201e5aa0af3.debug ..
--187198--   .. build-id is valid
--187198-- Reading syms from /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux
--187198--   Considering /usr/lib/debug/.build-id/54/299c4aec0e5e5f3d7b8135341351d0e1dbfc64.debug ..
--187198--   .. build-id is valid
--187198--    object doesn't have a dynamic symbol table
--187198-- Scheduler: using generic scheduler lock implementation.
--187198-- Reading suppressions file: /usr/lib/x86_64-linux-gnu/valgrind/default.supp
==187198== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-187198-by-soufiane-on-???
==187198== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-187198-by-soufiane-on-???
==187198== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-187198-by-soufiane-on-???
==187198== 
==187198== TO CONTROL THIS PROCESS USING vgdb (which you probably
==187198== don't want to do, unless you know exactly what you're doing,
==187198== or are doing some strange experiment):
==187198==   /usr/bin/vgdb --pid=187198 ...command...
==187198== 
==187198== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==187198==   /path/to/gdb CodeLite/build-Debug/bin/teset3
==187198== and then give GDB the following command
==187198==   target remote | /usr/bin/vgdb --pid=187198
==187198== --pid is optional if only one valgrind process is running
==187198== 
--187198-- REDIR: 0x401f820 (ld-linux-x86-64.so.2:strlen) redirected to 0x580ca5f2 (vgPlain_amd64_linux_REDIR_FOR_strlen)
--187198-- REDIR: 0x401f600 (ld-linux-x86-64.so.2:index) redirected to 0x580ca60c (vgPlain_amd64_linux_REDIR_FOR_index)
--187198-- Reading syms from /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_core-amd64-linux.so
--187198--   Considering /usr/lib/debug/.build-id/f2/7641e081d3c37b410d7f31da4e2bf21040f356.debug ..
--187198--   .. build-id is valid
--187198-- Reading syms from /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so
--187198--   Considering /usr/lib/debug/.build-id/25/7cdcdf80e04f91ca9e3b185ee3b52995e89946.debug ..
--187198--   .. build-id is valid
==187198== WARNING: new redirection conflicts with existing -- ignoring it
--187198--     old: 0x0401f820 (strlen              ) R-> (0000.0) 0x580ca5f2 vgPlain_amd64_linux_REDIR_FOR_strlen
--187198--     new: 0x0401f820 (strlen              ) R-> (2007.0) 0x0483bda0 strlen
--187198-- REDIR: 0x401c040 (ld-linux-x86-64.so.2:strcmp) redirected to 0x483cc90 (strcmp)
--187198-- REDIR: 0x401fd60 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4840740 (mempcpy)
--187198-- Reading syms from /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
--187198--    object doesn't have a symbol table
--187198-- Reading syms from /lib/x86_64-linux-gnu/libc-2.31.so
--187198--   Considering /usr/lib/debug/.build-id/11/79082c082db1c6e5578c4bda11061283b55ea1.debug ..
--187198--   .. build-id is valid
--187198-- Reading syms from /lib/x86_64-linux-gnu/libdl-2.31.so
--187198--   Considering /usr/lib/debug/.build-id/96/9e918a70cfb70b5b16ef417c282ab5b3bb0bc3.debug ..
--187198--   .. build-id is valid
--187198-- Reading syms from /lib/x86_64-linux-gnu/libpthread-2.31.so
--187198--   Considering /usr/lib/debug/.build-id/35/652c7fe24301abe3b020ee8f7a7921c6d10e1b.debug ..
--187198--   .. build-id is valid
--187198-- REDIR: 0x4bf8e40 (libc.so.6:memmove) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf81f0 (libc.so.6:strncpy) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf9160 (libc.so.6:strcasecmp) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf7b10 (libc.so.6:strcat) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8250 (libc.so.6:rindex) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bfa4f0 (libc.so.6:rawmemchr) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c126b0 (libc.so.6:wmemchr) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c12250 (libc.so.6:wcscmp) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8fa0 (libc.so.6:mempcpy) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8dd0 (libc.so.6:bcmp) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8190 (libc.so.6:strncmp) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf7bc0 (libc.so.6:strcmp) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8f00 (libc.so.6:memset) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c12210 (libc.so.6:wcschr) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf80f0 (libc.so.6:strnlen) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf7c90 (libc.so.6:strcspn) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf91b0 (libc.so.6:strncasecmp) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf7c30 (libc.so.6:strcpy) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf9300 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c138b0 (libc.so.6:wcsnlen) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c12290 (libc.so.6:wcscpy) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8290 (libc.so.6:strpbrk) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf7b70 (libc.so.6:index) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf80b0 (libc.so.6:strlen) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bfe850 (libc.so.6:memrchr) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf9200 (libc.so.6:strcasecmp_l) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8d90 (libc.so.6:memchr) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c12330 (libc.so.6:wcslen) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8530 (libc.so.6:strspn) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf9100 (libc.so.6:stpncpy) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf90a0 (libc.so.6:stpcpy) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bfa530 (libc.so.6:strchrnul) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf9250 (libc.so.6:strncasecmp_l) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c75510 (libc.so.6:__memcpy_chk) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4bf8cc0 (libc.so.6:strstr) redirected to 0x482e1b0 (_vgnU_ifunc_wrapper)
--187198-- REDIR: 0x4c074d0 (libc.so.6:__strrchr_sse2) redirected to 0x483b7f0 (__strrchr_sse2)
--187198-- REDIR: 0x4c077c0 (libc.so.6:__strlen_sse2) redirected to 0x483bce0 (__strlen_sse2)
--187198-- REDIR: 0x4bf4090 (libc.so.6:malloc) redirected to 0x4838710 (malloc)
--187198-- REDIR: 0x4c11a10 (libc.so.6:__memset_sse2_unaligned) redirected to 0x483f650 (memset)
--187198-- REDIR: 0x4c115f0 (libc.so.6:__memcpy_chk_sse2_unaligned) redirected to 0x4840820 (__memcpy_chk)
--187198-- REDIR: 0x4c11600 (libc.so.6:memcpy@GLIBC_2.2.5) redirected to 0x483cda0 (memcpy@GLIBC_2.2.5)
--187198-- REDIR: 0x4bf46c0 (libc.so.6:free) redirected to 0x4839940 (free)
--187198-- REDIR: 0x4c072c0 (libc.so.6:__strchrnul_sse2) redirected to 0x48402b0 (strchrnul)
--187198-- REDIR: 0x4c115e0 (libc.so.6:__mempcpy_sse2_unaligned) redirected to 0x48403c0 (mempcpy)
f79bb0d317b310b261a55a8ab393b4c8a1aba6fa4d08aef379caba502d5d67f9
==187198== Use of uninitialised value of size 8
==187198==    at 0x4BBAE3A: _itoa_word (_itoa.c:180)
==187198==    by 0x4BD4857: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
==187198== Conditional jump or move depends on uninitialised value(s)
==187198==    at 0x4BBAE4C: _itoa_word (_itoa.c:180)
==187198==    by 0x4BD4857: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
==187198== Conditional jump or move depends on uninitialised value(s)
==187198==    at 0x4BD5600: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
==187198== Conditional jump or move depends on uninitialised value(s)
==187198==    at 0x4BD49CE: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
8d0e28426b8fb0d774033f6c1cd3c5d597bb49cd03c3cf777d62f6feb9213cd0
==187198== 
==187198== HEAP SUMMARY:
==187198==     in use at exit: 0 bytes in 0 blocks
==187198==   total heap usage: 15 allocs, 15 frees, 2,720 bytes allocated
==187198== 
==187198== All heap blocks were freed -- no leaks are possible
==187198== 
==187198== ERROR SUMMARY: 186 errors from 4 contexts (suppressed: 0 from 0)
==187198== 
==187198== 32 errors in context 1 of 4:
==187198== Conditional jump or move depends on uninitialised value(s)
==187198==    at 0x4BD49CE: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
==187198== 
==187198== 32 errors in context 2 of 4:
==187198== Conditional jump or move depends on uninitialised value(s)
==187198==    at 0x4BD5600: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
==187198== 
==187198== 61 errors in context 3 of 4:
==187198== Conditional jump or move depends on uninitialised value(s)
==187198==    at 0x4BBAE4C: _itoa_word (_itoa.c:180)
==187198==    by 0x4BD4857: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
==187198== 
==187198== 61 errors in context 4 of 4:
==187198== Use of uninitialised value of size 8
==187198==    at 0x4BBAE3A: _itoa_word (_itoa.c:180)
==187198==    by 0x4BD4857: __vfprintf_internal (vfprintf-internal.c:1687)
==187198==    by 0x4BC0D3A: printf (printf.c:33)
==187198==    by 0x1092C4: main (main.c:40)
==187198==  Uninitialised value was created by a stack allocation
==187198==    at 0x109353: CKDPrivate (main.c:57)
==187198== 
==187198== ERROR SUMMARY: 186 errors from 4 contexts (suppressed: 0 from 0)

预期的结果是

56bd579906395c55b7e1707cebbfb96eccd5ecc6dccece47f79bcf255cd6ca9e

提前致谢

标签: cbitcoinsha512

解决方案


不清楚你想做什么但是:

unsigned char c[32],d[37];

d这里是 37 字节,但你告诉 HMAC 它是 64 字节长。

HMAC(EVP_sha512(),c,32,d,64,e,0);

考虑到您定义cd在此方法中,您可以:

HMAC(EVP_sha512(),c,sizeof(c),d,sizeof(d),e,NULL);

(HMAC的最后一个参数是unsigned int *md_len……我觉得用起来更易读NULL


推荐阅读