Skip to content

Instantly share code, notes, and snippets.

@theuni
Created January 14, 2015 09:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theuni/a64d9fd70fb7eab03186 to your computer and use it in GitHub Desktop.
Save theuni/a64d9fd70fb7eab03186 to your computer and use it in GitHub Desktop.
dersig constexpr evaluation
// Compile with: g++ -std=c++11 dersig.cpp -o dersig
#include <cstddef>
#include <vector>
#include <array>
inline constexpr char getHex(const char in)
{
return in >= '0' && in <= '9' ? in - '0' :
in >= 'A' && in <= 'F' ? in - 'A' + 10 :
in >= 'a' && in <= 'f' ? in - 'a' + 10 : -1;
}
template <size_t Length>
inline constexpr unsigned char getElem(const std::array<char, Length>& sig, unsigned int elem)
{
return static_cast<unsigned char>(getHex(sig.at((elem*2)+2)) << 4 | ( (elem*2)+3 < sig.size() ? getHex(sig.at((elem*2)+3)) : 0));
}
template <size_t Length>
inline constexpr unsigned int lenR(const std::array<char, Length>& sig)
{
return getElem(sig, 3);
}
template <size_t Length>
inline constexpr unsigned int lenS(const std::array<char, Length>& sig)
{
return getElem(sig, 5 + lenR(sig));
}
template <size_t Length>
inline constexpr size_t sigSize(const std::array<char, Length>& sig)
{
return (sig.size() - 1) / 2;
}
template <size_t Length>
inline constexpr bool IsDERSignature(const std::array<char, Length> sig)
{
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
// * total-length: 1-byte length descriptor of everything that follows,
// excluding the sighash byte.
// * R-length: 1-byte length descriptor of the R value that follows.
// * R: arbitrary-length big-endian encoded R value. It cannot start with any
// null bytes, unless the first byte that follows is 0x80 or higher, in which
// case a single null byte is required.
// * S-length: 1-byte length descriptor of the S value that follows.
// * S: arbitrary-length big-endian encoded S value. The same rules apply.
// * sighash: 1-byte value indicating what data is hashed.
// Accept empty signature as correctly encoded (but invalid) signature,
// even though it is not strictly DER.
return (sigSize(sig) == 0) ||
(
// Minimum and maximum size constraints.
sigSize(sig) >= 9 && sigSize(sig) <= 73 &&
// A signature is of type 0x30 (compound).
getElem(sig,0) == 0x30 &&
// Make sure the length covers the entire signature.
getElem(sig,1) == sigSize(sig) - 3 &&
// Make sure the length of the S element is still inside the signature.
lenR(sig) + 5 < sigSize(sig) &&
// Verify that the length of the signature matches the sum of the length
// of the elements.
static_cast<size_t>(lenS(sig) + lenR(sig) + 7) == sigSize(sig) &&
// Check whether the R element is an integer.
getElem(sig,2) == 0x02 &&
// Zero-length integers are not allowed for R.
lenR(sig) != 0 &&
// Negative numbers are not allowed for R.
(getElem(sig,4) & 0x80) == 0 &&
// Zero bytes at the start of R are not allowed, unless it would
// otherwise be interpreted as a negative number.
!(lenR(sig) > 1 && (getElem(sig,4) == 0x00) && !(getElem(sig,5) & 0x80)) &&
// Check whether the S element is an integer.
getElem(sig,lenR(sig) + 4) == 0x02 &&
// Zero-length integers are not allowed for S.
lenS(sig) != 0 &&
// Negative numbers are not allowed for S.
(getElem(sig,lenR(sig) + 6) & 0x80) == 0 &&
// Null bytes at the start of R are not allowed, unless it would otherwise be
// interpreted as a negative number.
!(lenS(sig) > 1 && (getElem(sig,lenR(sig) + 6) == 0x00) && !(getElem(sig,lenR(sig) + 7) & 0x80))
);
}
template <char... Args>
std::vector<unsigned char> operator "" _der()
{
constexpr std::array<char, sizeof...(Args)> temp{{Args...}};
static_assert(IsDERSignature(std::array<char,temp.size()>(temp)), "invalid der");
std::vector<unsigned char> ret(sigSize(temp));
for (auto i : ret)
ret[i] = getElem(temp, i);
return ret;
}
int main()
{
typedef std::vector<unsigned char> der_type;
der_type foo = 0x304402202cb265bf10707bf49346c3515dd3d16fc454618c58ec0a0ff448a676c54ff71302206c6624d762a1fcef4618284ead8f08678ac05b13c84235f1654e6ad168233e8201_der;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment