Browse Source
2bfb82b Merge pull request #351 06aeea5 Turn secp256k1_ec_pubkey_serialize outlen to in/out 970164d Merge pull request #348 6466625 Improvements for coordinate decompression e2100ad Merge pull request #347 8e48787 Change secp256k1_ec_pubkey_combine's count argument to size_t. c69dea0 Clear output in more cases for pubkey_combine, adds tests. 269d422 Comment copyediting. b4d17da Merge pull request #344 4709265 Merge pull request #345 26abce7 Adds 32 static test vectors for scalar mul, sqr, inv. 5b71a3f Better error case handling for pubkey_create & pubkey_serialize, more tests. 3b7bc69 Merge pull request #343 eed87af Change contrib/laxder from headers-only to files compilable as standalone C d7eb1ae Merge pull request #342 7914a6e Make lax_der_privatekey_parsing.h not depend on internal code 73f64ff Merge pull request #339 9234391 Overhaul flags handling 1a36898 Make flags more explicit, add runtime checks. 1a3e03a Merge pull request #340 96be204 Add additional tests for eckey and arg-checks. bb5aa4d Make the tweak function zeroize-output-on-fail behavior consistent. 4a243da Move secp256k1_ec_privkey_import/export to contrib. 1b3efc1 Move secp256k1_ecdsa_sig_recover into the recovery module. e3cd679 Eliminate all side-effects from VERIFY_CHECK() usage. b30fc85 Avoid nonce_function_rfc6979 algo16 argument emulation. 70d4640 Make secp256k1_ec_pubkey_create skip processing invalid secret keys. 6c476a8 Minor comment improvements. 131afe5 Merge pull request #334 0c6ab2f Introduce explicit lower-S normalization fea19e7 Add contrib/lax_der_parsing.h 3bb9c44 Rewrite ECDSA signature parsing code fa57f1b Use secp256k1_rand_int and secp256k1_rand_bits more 49b3749 Add new tests for the extra testrand functions f684d7d Faster secp256k1_rand_int implementation 251b1a6 Improve testrand: add extra random functions 31994c8 Merge pull request #338 f79aa88 Bugfix: swap arguments to noncefp c98df26 Merge pull request #319 67f7da4 Extensive interface and operations tests for secp256k1_ec_pubkey_parse. ee2cb40 Add ARG_CHECKs to secp256k1_ec_pubkey_parse/secp256k1_ec_pubkey_serialize 7450ef1 Merge pull request #328 68a3c76 Merge pull request #329 98135ee Merge pull request #332 37100d7 improve ECDH header-doc b13d749 Fix couple of typos in API comments 7c823e3 travis: fixup module configs cc3141a Merge pull request #325 ee58fae Merge pull request #326 213aa67 Do not force benchmarks to be statically linked. 338fc8b Add API exports to secp256k1_nonce_function_default and secp256k1_nonce_function_rfc6979. 52fd03f Merge pull request #320 9f6993f Remove some dead code. 357f8cd Merge pull request #314 118cd82 Use explicit symbol visibility. 4e64608 Include public module headers when compiling modules. 1f41437 Merge pull request #316 fe0d463 Merge pull request #317 cfe0ed9 Fix miscellaneous style nits that irritate overactive static analysis. 2b199de Use the explicit NULL macro for pointer comparisons. 9e90516 Merge pull request #294 dd891e0 Get rid of _t as it is POSIX reserved 201819b Merge pull request #313 912f203 Eliminate a few unbraced statements that crept into the code. eeab823 Merge pull request #299 486b9bb Use a flags bitfield for compressed option to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export 05732c5 Callback data: Accept pointers to either const or non-const data 1973c73 Bugfix: Reinitialise buffer lengths that have been used as outputs 788038d Use size_t for lengths (at least in external API) c9d7c2a secp256k1_context_set_{error,illegal}_callback: Restore default handler by passing NULL as function argument 9aac008 secp256k1_context_destroy: Allow NULL argument as a no-op 64b730b secp256k1_context_create: Use unsigned type for flags bitfield cb04ab5 Merge pull request #309 a551669 Merge pull request #295 81e45ff Update group_impl.h 85e3a2c Merge pull request #112 b2eb63b Merge pull request #293 dc0ce9f [API BREAK] Change argument order to out/outin/in 6d947ca Merge pull request #298 c822693 Merge pull request #301 6d04350 Merge pull request #303 7ab311c Merge pull request #304 5fb3229 Fixes a bug where bench_sign would fail due to passing in too small a buffer. 263dcbc remove unused assignment b183b41 bugfix: "ARG_CHECK(ctx != NULL)" makes no sense 6da1446 build: fix parallel build 5eb4356 Merge pull request #291 c996d53 Print success 9f443be Move pubkey recovery code to separate module d49abbd Separate ECDSA recovery tests 439d34a Separate recoverable and normal signatures a7b046e Merge pull request #289 f66907f Improve/reformat API documentation secp256k1.h 2f77487 Add context building benchmarks cc623d5 Merge pull request #287 de7e398 small typo fix 9d96e36 Merge pull request #280 432e1ce Merge pull request #283 14727fd Use correct name in gitignore 356b0e9 Actually test static precomputation in Travis ff3a5df Merge pull request #284 2587208 Merge pull request #212 a5a66c7 Add support for custom EC-Schnorr-SHA256 signatures d84a378 Merge pull request #252 72ae443 Improve perf. of cmov-based table lookup 92e53fc Implement endomorphism optimization for secp256k1_ecmult_const ed35d43 Make `secp256k1_scalar_add_bit` conditional; make `secp256k1_scalar_split_lambda_var` constant time 91c0ce9 Add benchmarks for ECDH and const-time multiplication 0739bbb Add ECDH module which works by hashing the output of ecmult_const 4401500 Add constant-time multiply `secp256k1_ecmult_const` for ECDH e4ce393 build: fix hard-coded usage of "gen_context" b8e39ac build: don't use BUILT_SOURCES for the static context header baa75da tests: add a couple tests ae4f0c6 Merge pull request #278 995c548 Introduce callback functions for dealing with errors. c333074 Merge pull request #282 18c329c Remove the internal secp256k1_ecdsa_sig_t type 74a2acd Add a secp256k1_ecdsa_signature_t type 23cfa91 Introduce secp256k1_pubkey_t type 4c63780 Merge pull request #269 3e6f1e2 Change rfc6979 implementation to be a generic PRNG ed5334a Update configure.ac to make it build on OpenBSD 1b68366 Merge pull request #274 a83bb48 Make ecmult static precomputation default 166b32f Merge pull request #276 c37812f Add gen_context src/ecmult_static_context.h to CLEANFILES to fix distclean. 125c15d Merge pull request #275 76f6769 Fix build with static ecmult altroot and make dist. 5133f78 Merge pull request #254 b0a60e6 Merge pull request #258 733c1e6 Add travis build to test the static context. fbecc38 Add ability to use a statically generated ecmult context. 4fb174d Merge pull request #263 4ab8990 Merge pull request #270 bdf0e0c Merge pull request #271 31d0c1f Merge pull request #273 eb2c8ff Add missing casts to SECP256K1_FE_CONST_INNER 55399c2 Further performance improvements to _ecmult_wnaf 99fd963 Add secp256k1_ec_pubkey_compress(), with test similar to the related decompress() function. 145cc6e Improve performance of _ecmult_wnaf 36b305a Verify the result of GMP modular inverse using non-GMP code 0cbc860 Merge pull request #266 06ff7fe Merge pull request #267 5a43124 Save 1 _fe_negate since s1 == -s2 a5d796e Update code comments 3f3964e Add specific VERIFY tests for _fe_cmov 7d054cd Refactor to save a _fe_negate b28d02a Refactor to remove a local var 55e7fc3 Perf. improvement in _gej_add_ge a0601cd Fix VERIFY calculations in _fe_cmov methods 17f7148 Merge pull request #261 7657420 Add tests for adding P+Q with P.x!=Q.x and P.y=-Q.y 8c5d5f7 tests: Add failing unit test for #257 (bad addition formula) 5de4c5d gej_add_ge: fix degenerate case when computing P + (-lambda)P bcf2fcf gej_add_ge: rearrange algebra e2a07c7 Fix compilation with C++ 873a453 Merge pull request #250 91eb0da Merge pull request #247 210ffed Use separate in and out pointers in `secp256k1_ec_pubkey_decompress` a1d5ae1 Tiny optimization 729badf Merge pull request #210 2d5a186 Apply effective-affine trick to precomp 4f9791a Effective affine addition in EC multiplication 2b4cf41 Use pkg-config always when possible, with failover to manual checks for libcrypto git-subtree-dir: src/secp256k1 git-subtree-split: 2bfb82b10edf0f0b0e366a12f94c8b21a914159dpull/1/head
68 changed files with 7728 additions and 1916 deletions
@ -0,0 +1,125 @@
@@ -0,0 +1,125 @@
|
||||
# =========================================================================== |
||||
# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html |
||||
# =========================================================================== |
||||
# |
||||
# SYNOPSIS |
||||
# |
||||
# AX_PROG_CC_FOR_BUILD |
||||
# |
||||
# DESCRIPTION |
||||
# |
||||
# This macro searches for a C compiler that generates native executables, |
||||
# that is a C compiler that surely is not a cross-compiler. This can be |
||||
# useful if you have to generate source code at compile-time like for |
||||
# example GCC does. |
||||
# |
||||
# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything |
||||
# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). |
||||
# The value of these variables can be overridden by the user by specifying |
||||
# a compiler with an environment variable (like you do for standard CC). |
||||
# |
||||
# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object |
||||
# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if |
||||
# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are |
||||
# substituted in the Makefile. |
||||
# |
||||
# LICENSE |
||||
# |
||||
# Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org> |
||||
# |
||||
# Copying and distribution of this file, with or without modification, are |
||||
# permitted in any medium without royalty provided the copyright notice |
||||
# and this notice are preserved. This file is offered as-is, without any |
||||
# warranty. |
||||
|
||||
#serial 8 |
||||
|
||||
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) |
||||
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl |
||||
AC_REQUIRE([AC_PROG_CC])dnl |
||||
AC_REQUIRE([AC_PROG_CPP])dnl |
||||
AC_REQUIRE([AC_EXEEXT])dnl |
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl |
||||
|
||||
dnl Use the standard macros, but make them use other variable names |
||||
dnl |
||||
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl |
||||
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl |
||||
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl |
||||
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl |
||||
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl |
||||
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl |
||||
pushdef([ac_cv_objext], ac_cv_build_objext)dnl |
||||
pushdef([ac_exeext], ac_build_exeext)dnl |
||||
pushdef([ac_objext], ac_build_objext)dnl |
||||
pushdef([CC], CC_FOR_BUILD)dnl |
||||
pushdef([CPP], CPP_FOR_BUILD)dnl |
||||
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl |
||||
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl |
||||
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl |
||||
pushdef([host], build)dnl |
||||
pushdef([host_alias], build_alias)dnl |
||||
pushdef([host_cpu], build_cpu)dnl |
||||
pushdef([host_vendor], build_vendor)dnl |
||||
pushdef([host_os], build_os)dnl |
||||
pushdef([ac_cv_host], ac_cv_build)dnl |
||||
pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl |
||||
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl |
||||
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl |
||||
pushdef([ac_cv_host_os], ac_cv_build_os)dnl |
||||
pushdef([ac_cpp], ac_build_cpp)dnl |
||||
pushdef([ac_compile], ac_build_compile)dnl |
||||
pushdef([ac_link], ac_build_link)dnl |
||||
|
||||
save_cross_compiling=$cross_compiling |
||||
save_ac_tool_prefix=$ac_tool_prefix |
||||
cross_compiling=no |
||||
ac_tool_prefix= |
||||
|
||||
AC_PROG_CC |
||||
AC_PROG_CPP |
||||
AC_EXEEXT |
||||
|
||||
ac_tool_prefix=$save_ac_tool_prefix |
||||
cross_compiling=$save_cross_compiling |
||||
|
||||
dnl Restore the old definitions |
||||
dnl |
||||
popdef([ac_link])dnl |
||||
popdef([ac_compile])dnl |
||||
popdef([ac_cpp])dnl |
||||
popdef([ac_cv_host_os])dnl |
||||
popdef([ac_cv_host_vendor])dnl |
||||
popdef([ac_cv_host_cpu])dnl |
||||
popdef([ac_cv_host_alias])dnl |
||||
popdef([ac_cv_host])dnl |
||||
popdef([host_os])dnl |
||||
popdef([host_vendor])dnl |
||||
popdef([host_cpu])dnl |
||||
popdef([host_alias])dnl |
||||
popdef([host])dnl |
||||
popdef([LDFLAGS])dnl |
||||
popdef([CPPFLAGS])dnl |
||||
popdef([CFLAGS])dnl |
||||
popdef([CPP])dnl |
||||
popdef([CC])dnl |
||||
popdef([ac_objext])dnl |
||||
popdef([ac_exeext])dnl |
||||
popdef([ac_cv_objext])dnl |
||||
popdef([ac_cv_exeext])dnl |
||||
popdef([ac_cv_prog_cc_g])dnl |
||||
popdef([ac_cv_prog_cc_cross])dnl |
||||
popdef([ac_cv_prog_cc_works])dnl |
||||
popdef([ac_cv_prog_gcc])dnl |
||||
popdef([ac_cv_prog_CPP])dnl |
||||
|
||||
dnl Finally, set Makefile variables |
||||
dnl |
||||
BUILD_EXEEXT=$ac_build_exeext |
||||
BUILD_OBJEXT=$ac_build_objext |
||||
AC_SUBST(BUILD_EXEEXT)dnl |
||||
AC_SUBST(BUILD_OBJEXT)dnl |
||||
AC_SUBST([CFLAGS_FOR_BUILD])dnl |
||||
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl |
||||
AC_SUBST([LDFLAGS_FOR_BUILD])dnl |
||||
]) |
@ -0,0 +1,150 @@
@@ -0,0 +1,150 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#include <string.h> |
||||
#include <secp256k1.h> |
||||
|
||||
#include "lax_der_parsing.h" |
||||
|
||||
int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { |
||||
size_t rpos, rlen, spos, slen; |
||||
size_t pos = 0; |
||||
size_t lenbyte; |
||||
unsigned char tmpsig[64] = {0}; |
||||
int overflow = 0; |
||||
|
||||
/* Hack to initialize sig with a correctly-parsed but invalid signature. */ |
||||
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); |
||||
|
||||
/* Sequence tag byte */ |
||||
if (pos == inputlen || input[pos] != 0x30) { |
||||
return 0; |
||||
} |
||||
pos++; |
||||
|
||||
/* Sequence length bytes */ |
||||
if (pos == inputlen) { |
||||
return 0; |
||||
} |
||||
lenbyte = input[pos++]; |
||||
if (lenbyte & 0x80) { |
||||
lenbyte -= 0x80; |
||||
if (pos + lenbyte > inputlen) { |
||||
return 0; |
||||
} |
||||
pos += lenbyte; |
||||
} |
||||
|
||||
/* Integer tag byte for R */ |
||||
if (pos == inputlen || input[pos] != 0x02) { |
||||
return 0; |
||||
} |
||||
pos++; |
||||
|
||||
/* Integer length for R */ |
||||
if (pos == inputlen) { |
||||
return 0; |
||||
} |
||||
lenbyte = input[pos++]; |
||||
if (lenbyte & 0x80) { |
||||
lenbyte -= 0x80; |
||||
if (pos + lenbyte > inputlen) { |
||||
return 0; |
||||
} |
||||
while (lenbyte > 0 && input[pos] == 0) { |
||||
pos++; |
||||
lenbyte--; |
||||
} |
||||
if (lenbyte >= sizeof(size_t)) { |
||||
return 0; |
||||
} |
||||
rlen = 0; |
||||
while (lenbyte > 0) { |
||||
rlen = (rlen << 8) + input[pos]; |
||||
pos++; |
||||
lenbyte--; |
||||
} |
||||
} else { |
||||
rlen = lenbyte; |
||||
} |
||||
if (rlen > inputlen - pos) { |
||||
return 0; |
||||
} |
||||
rpos = pos; |
||||
pos += rlen; |
||||
|
||||
/* Integer tag byte for S */ |
||||
if (pos == inputlen || input[pos] != 0x02) { |
||||
return 0; |
||||
} |
||||
pos++; |
||||
|
||||
/* Integer length for S */ |
||||
if (pos == inputlen) { |
||||
return 0; |
||||
} |
||||
lenbyte = input[pos++]; |
||||
if (lenbyte & 0x80) { |
||||
lenbyte -= 0x80; |
||||
if (pos + lenbyte > inputlen) { |
||||
return 0; |
||||
} |
||||
while (lenbyte > 0 && input[pos] == 0) { |
||||
pos++; |
||||
lenbyte--; |
||||
} |
||||
if (lenbyte >= sizeof(size_t)) { |
||||
return 0; |
||||
} |
||||
slen = 0; |
||||
while (lenbyte > 0) { |
||||
slen = (slen << 8) + input[pos]; |
||||
pos++; |
||||
lenbyte--; |
||||
} |
||||
} else { |
||||
slen = lenbyte; |
||||
} |
||||
if (slen > inputlen - pos) { |
||||
return 0; |
||||
} |
||||
spos = pos; |
||||
pos += slen; |
||||
|
||||
/* Ignore leading zeroes in R */ |
||||
while (rlen > 0 && input[rpos] == 0) { |
||||
rlen--; |
||||
rpos++; |
||||
} |
||||
/* Copy R value */ |
||||
if (rlen > 32) { |
||||
overflow = 1; |
||||
} else { |
||||
memcpy(tmpsig + 32 - rlen, input + rpos, rlen); |
||||
} |
||||
|
||||
/* Ignore leading zeroes in S */ |
||||
while (slen > 0 && input[spos] == 0) { |
||||
slen--; |
||||
spos++; |
||||
} |
||||
/* Copy S value */ |
||||
if (slen > 32) { |
||||
overflow = 1; |
||||
} else { |
||||
memcpy(tmpsig + 64 - slen, input + spos, slen); |
||||
} |
||||
|
||||
if (!overflow) { |
||||
overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); |
||||
} |
||||
if (overflow) { |
||||
memset(tmpsig, 0, 64); |
||||
secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); |
||||
} |
||||
return 1; |
||||
} |
||||
|
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
/****
|
||||
* Please do not link this file directly. It is not part of the libsecp256k1 |
||||
* project and does not promise any stability in its API, functionality or |
||||
* presence. Projects which use this code should instead copy this header |
||||
* and its accompanying .c file directly into their codebase. |
||||
****/ |
||||
|
||||
/* This file defines a function that parses DER with various errors and
|
||||
* violations. This is not a part of the library itself, because the allowed |
||||
* violations are chosen arbitrarily and do not follow or establish any |
||||
* standard. |
||||
* |
||||
* In many places it matters that different implementations do not only accept |
||||
* the same set of valid signatures, but also reject the same set of signatures. |
||||
* The only means to accomplish that is by strictly obeying a standard, and not |
||||
* accepting anything else. |
||||
* |
||||
* Nonetheless, sometimes there is a need for compatibility with systems that |
||||
* use signatures which do not strictly obey DER. The snippet below shows how |
||||
* certain violations are easily supported. You may need to adapt it. |
||||
* |
||||
* Do not use this for new systems. Use well-defined DER or compact signatures |
||||
* instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and |
||||
* secp256k1_ecdsa_signature_parse_compact). |
||||
* |
||||
* The supported violations are: |
||||
* - All numbers are parsed as nonnegative integers, even though X.609-0207 |
||||
* section 8.3.3 specifies that integers are always encoded as two's |
||||
* complement. |
||||
* - Integers can have length 0, even though section 8.3.1 says they can't. |
||||
* - Integers with overly long padding are accepted, violation section |
||||
* 8.3.2. |
||||
* - 127-byte long length descriptors are accepted, even though section |
||||
* 8.1.3.5.c says that they are not. |
||||
* - Trailing garbage data inside or after the signature is ignored. |
||||
* - The length descriptor of the sequence is ignored. |
||||
* |
||||
* Compared to for example OpenSSL, many violations are NOT supported: |
||||
* - Using overly long tag descriptors for the sequence or integers inside, |
||||
* violating section 8.1.2.2. |
||||
* - Encoding primitive integers as constructed values, violating section |
||||
* 8.3.1. |
||||
*/ |
||||
|
||||
#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ |
||||
#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ |
||||
|
||||
#include <secp256k1.h> |
||||
|
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
|
||||
/** Parse a signature in "lax DER" format
|
||||
* |
||||
* Returns: 1 when the signature could be parsed, 0 otherwise. |
||||
* Args: ctx: a secp256k1 context object |
||||
* Out: sig: a pointer to a signature object |
||||
* In: input: a pointer to the signature to be parsed |
||||
* inputlen: the length of the array pointed to be input |
||||
* |
||||
* This function will accept any valid DER encoded signature, even if the |
||||
* encoded numbers are out of range. In addition, it will accept signatures |
||||
* which violate the DER spec in various ways. Its purpose is to allow |
||||
* validation of the Bitcoin blockchain, which includes non-DER signatures |
||||
* from before the network rules were updated to enforce DER. Note that |
||||
* the set of supported violations is a strict subset of what OpenSSL will |
||||
* accept. |
||||
* |
||||
* After the call, sig will always be initialized. If parsing failed or the |
||||
* encoded numbers are out of range, signature validation with it is |
||||
* guaranteed to fail for every message and public key. |
||||
*/ |
||||
int ecdsa_signature_parse_der_lax( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_ecdsa_signature* sig, |
||||
const unsigned char *input, |
||||
size_t inputlen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014, 2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#include <string.h> |
||||
#include <secp256k1.h> |
||||
|
||||
#include "lax_der_privatekey_parsing.h" |
||||
|
||||
int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { |
||||
const unsigned char *end = privkey + privkeylen; |
||||
int lenb = 0; |
||||
int len = 0; |
||||
memset(out32, 0, 32); |
||||
/* sequence header */ |
||||
if (end < privkey+1 || *privkey != 0x30) { |
||||
return 0; |
||||
} |
||||
privkey++; |
||||
/* sequence length constructor */ |
||||
if (end < privkey+1 || !(*privkey & 0x80)) { |
||||
return 0; |
||||
} |
||||
lenb = *privkey & ~0x80; privkey++; |
||||
if (lenb < 1 || lenb > 2) { |
||||
return 0; |
||||
} |
||||
if (end < privkey+lenb) { |
||||
return 0; |
||||
} |
||||
/* sequence length */ |
||||
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); |
||||
privkey += lenb; |
||||
if (end < privkey+len) { |
||||
return 0; |
||||
} |
||||
/* sequence element 0: version number (=1) */ |
||||
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { |
||||
return 0; |
||||
} |
||||
privkey += 3; |
||||
/* sequence element 1: octet string, up to 32 bytes */ |
||||
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { |
||||
return 0; |
||||
} |
||||
memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); |
||||
if (!secp256k1_ec_seckey_verify(ctx, out32)) { |
||||
memset(out32, 0, 32); |
||||
return 0; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { |
||||
secp256k1_pubkey pubkey; |
||||
size_t pubkeylen = 0; |
||||
if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { |
||||
*privkeylen = 0; |
||||
return 0; |
||||
} |
||||
if (compressed) { |
||||
static const unsigned char begin[] = { |
||||
0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 |
||||
}; |
||||
static const unsigned char middle[] = { |
||||
0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, |
||||
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, |
||||
0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, |
||||
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, |
||||
0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, |
||||
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 |
||||
}; |
||||
unsigned char *ptr = privkey; |
||||
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); |
||||
memcpy(ptr, key32, 32); ptr += 32; |
||||
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); |
||||
pubkeylen = 33; |
||||
secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); |
||||
ptr += pubkeylen; |
||||
*privkeylen = ptr - privkey; |
||||
} else { |
||||
static const unsigned char begin[] = { |
||||
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 |
||||
}; |
||||
static const unsigned char middle[] = { |
||||
0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, |
||||
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, |
||||
0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, |
||||
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, |
||||
0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, |
||||
0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, |
||||
0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, |
||||
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 |
||||
}; |
||||
unsigned char *ptr = privkey; |
||||
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); |
||||
memcpy(ptr, key32, 32); ptr += 32; |
||||
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); |
||||
pubkeylen = 65; |
||||
secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); |
||||
ptr += pubkeylen; |
||||
*privkeylen = ptr - privkey; |
||||
} |
||||
return 1; |
||||
} |
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014, 2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
/****
|
||||
* Please do not link this file directly. It is not part of the libsecp256k1 |
||||
* project and does not promise any stability in its API, functionality or |
||||
* presence. Projects which use this code should instead copy this header |
||||
* and its accompanying .c file directly into their codebase. |
||||
****/ |
||||
|
||||
/* This file contains code snippets that parse DER private keys with
|
||||
* various errors and violations. This is not a part of the library |
||||
* itself, because the allowed violations are chosen arbitrarily and |
||||
* do not follow or establish any standard. |
||||
* |
||||
* It also contains code to serialize private keys in a compatible |
||||
* manner. |
||||
* |
||||
* These functions are meant for compatibility with applications |
||||
* that require BER encoded keys. When working with secp256k1-specific |
||||
* code, the simple 32-byte private keys normally used by the |
||||
* library are sufficient. |
||||
*/ |
||||
|
||||
#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ |
||||
#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ |
||||
|
||||
#include <secp256k1.h> |
||||
|
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
|
||||
/** Export a private key in DER format.
|
||||
* |
||||
* Returns: 1 if the private key was valid. |
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot |
||||
* be NULL) |
||||
* Out: privkey: pointer to an array for storing the private key in BER. |
||||
* Should have space for 279 bytes, and cannot be NULL. |
||||
* privkeylen: Pointer to an int where the length of the private key in |
||||
* privkey will be stored. |
||||
* In: seckey: pointer to a 32-byte secret key to export. |
||||
* compressed: 1 if the key should be exported in |
||||
* compressed format, 0 otherwise |
||||
* |
||||
* This function is purely meant for compatibility with applications that |
||||
* require BER encoded keys. When working with secp256k1-specific code, the |
||||
* simple 32-byte private keys are sufficient. |
||||
* |
||||
* Note that this function does not guarantee correct DER output. It is |
||||
* guaranteed to be parsable by secp256k1_ec_privkey_import_der |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *privkey, |
||||
size_t *privkeylen, |
||||
const unsigned char *seckey, |
||||
int compressed |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Import a private key in DER format.
|
||||
* Returns: 1 if a private key was extracted. |
||||
* Args: ctx: pointer to a context object (cannot be NULL). |
||||
* Out: seckey: pointer to a 32-byte array for storing the private key. |
||||
* (cannot be NULL). |
||||
* In: privkey: pointer to a private key in DER format (cannot be NULL). |
||||
* privkeylen: length of the DER private key pointed to be privkey. |
||||
* |
||||
* This function will accept more than just strict DER, and even allow some BER |
||||
* violations. The public key stored inside the DER-encoded private key is not |
||||
* verified for correctness, nor are the curve parameters. Use this function |
||||
* only if you know in advance it is supposed to contain a secp256k1 private |
||||
* key. |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *seckey, |
||||
const unsigned char *privkey, |
||||
size_t privkeylen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |