mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-17 04:39:36 +00:00
Add ed25519 private key search ##search
This commit is contained in:
parent
3f41b0a055
commit
3270166fa3
1
dist/plugins-cfg/plugins.nocs.cfg
vendored
1
dist/plugins-cfg/plugins.nocs.cfg
vendored
@ -133,6 +133,7 @@ core.sixref
|
||||
core.java
|
||||
crypto.aes
|
||||
crypto.des
|
||||
crypto.ed25519
|
||||
crypto.rc4
|
||||
crypto.cps2
|
||||
crypto.xor
|
||||
|
1
dist/plugins-cfg/plugins.static.nogpl.cfg
vendored
1
dist/plugins-cfg/plugins.static.nogpl.cfg
vendored
@ -97,6 +97,7 @@ core.a2f
|
||||
core.java
|
||||
crypto.aes
|
||||
crypto.des
|
||||
crypto.ed25519
|
||||
crypto.rc4
|
||||
crypto.cps2
|
||||
crypto.xor
|
||||
|
1
dist/plugins-cfg/plugins.wasi.cfg
vendored
1
dist/plugins-cfg/plugins.wasi.cfg
vendored
@ -19,6 +19,7 @@ arch.z80
|
||||
esil.null
|
||||
esil.dummy
|
||||
crypto.base64
|
||||
crypto.ed25519
|
||||
crypto.xor
|
||||
crypto.aes
|
||||
fs.posix
|
||||
|
@ -11,7 +11,9 @@ static int cmd_search(void *data, const char *input);
|
||||
|
||||
#define AES_SEARCH_LENGTH 40
|
||||
#define SM4_SEARCH_LENGTH 24
|
||||
#define PRIVATE_KEY_SEARCH_LENGTH 11
|
||||
#define ASN1_PRIVATE_KEY_SEARCH_LENGTH 11
|
||||
#define RAW_PRIVATE_KEY_SEARCH_LENGTH 32
|
||||
#define ED25519_PUBKEY_LENGTH 32*2
|
||||
|
||||
static RCoreHelpMessage help_msg_slash_wide_string = {
|
||||
"Usage: /w[ij]", "[str]", "Wide string search subcommands",
|
||||
@ -171,6 +173,7 @@ static RCoreHelpMessage help_msg_slash_c = {
|
||||
"/cd", "", "search for ASN1/DER certificates",
|
||||
"/cg", "", "search for GPG/PGP keys and signatures (Plaintext and binary form)",
|
||||
"/ck", "", "find well known constant tables from different hash and crypto algorithms",
|
||||
"/cp", "[?] [algo] [pubkey]", "search for a private key matching a given public key",
|
||||
"/cr", "", "search for ASN1/DER private keys (RSA and ECC)",
|
||||
NULL
|
||||
};
|
||||
@ -4507,13 +4510,50 @@ reread:
|
||||
}
|
||||
kw = r_search_keyword_new_hexmask ("00", NULL);
|
||||
// Private key search is at least 11 bytes
|
||||
kw->keyword_length = PRIVATE_KEY_SEARCH_LENGTH;
|
||||
r_search_reset (core->search, R_SEARCH_PRIV_KEY);
|
||||
kw->keyword_length = ASN1_PRIVATE_KEY_SEARCH_LENGTH;
|
||||
r_search_reset (core->search, R_SEARCH_ASN1_PRIV_KEY);
|
||||
r_search_kw_add (search, kw);
|
||||
r_search_begin (core->search);
|
||||
param.key_search = true;
|
||||
break;
|
||||
}
|
||||
case 'p': // "/cp"
|
||||
{
|
||||
RSearchKeyword *kw;
|
||||
char *space = strchr (input, ' ');
|
||||
const char *arg = space? r_str_trim_head_ro (space + 1): NULL;
|
||||
if (!arg || *(space - 1) == '?') {
|
||||
r_core_cmd_help_match (core, help_msg_slash_c, "/cp");
|
||||
goto beach;
|
||||
}
|
||||
|
||||
char *pubkey = strdup (r_str_trim_head_ro (strchr (arg, ' ')));
|
||||
char *algo = strdup (arg);
|
||||
r_str_split (algo, ' ');
|
||||
if (input[2] == 'j') {
|
||||
param.outmode = R_MODE_JSON;
|
||||
}
|
||||
if (!strcmp (algo, "ed25519")) {
|
||||
r_search_reset (core->search, R_SEARCH_RAW_PRIV_KEY);
|
||||
} else {
|
||||
R_LOG_ERROR ("Unsupported signature: %s", arg);
|
||||
goto beach;
|
||||
}
|
||||
if (strlen (pubkey) == ED25519_PUBKEY_LENGTH) {
|
||||
core->search->data = (void *)pubkey;
|
||||
} else {
|
||||
R_LOG_ERROR ("Wrong key length");
|
||||
goto beach;
|
||||
}
|
||||
kw = r_search_keyword_new_hexmask ("00", NULL);
|
||||
// Private key search is at least 32 bytes
|
||||
kw->keyword_length = RAW_PRIVATE_KEY_SEARCH_LENGTH;
|
||||
r_search_kw_add (search, kw);
|
||||
r_search_begin (core->search);
|
||||
param.key_search = true;
|
||||
free (algo);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
dosearch = false;
|
||||
r_core_cmd_help (core, help_msg_slash_c);
|
||||
|
@ -4,27 +4,41 @@
|
||||
|
||||
#include <r_lib.h>
|
||||
#include <r_crypto.h>
|
||||
#include <r_crypto/r_ed25519.h>
|
||||
#include <r_util/r_log.h>
|
||||
#include "../signature/ed25519/ge.h"
|
||||
#include "../signature/ed25519/sc.h"
|
||||
#include "../hash/sha2.h"
|
||||
|
||||
#define ED25519_SIG_LEN 64
|
||||
R_API void ed25519_create_keypair(const ut8 *seed, ut8 *privkey, ut8 *pubkey) {
|
||||
RHash *ctx = r_hash_new (true, R_HASH_SHA512);
|
||||
ge_p3 A;
|
||||
|
||||
r_hash_do_sha512 (ctx, seed, ED25519_SEED_LENGTH);
|
||||
memcpy (privkey, ctx->digest, ED25519_PRIVKEY_LENGTH);
|
||||
r_hash_free (ctx);
|
||||
privkey[0] &= 248;
|
||||
privkey[31] &= 63;
|
||||
privkey[31] |= 64;
|
||||
ge_scalarmult_base (&A, privkey);
|
||||
ge_p3_tobytes (pubkey, &A);
|
||||
}
|
||||
|
||||
static bool ed25519_set_key(RCryptoJob *cj, const ut8 *key, int keylen, int mode, int direction) {
|
||||
if (keylen != 32 && keylen != 64) {
|
||||
return false;
|
||||
}
|
||||
if (keylen == 32) {
|
||||
cj->data = malloc (ED25519_PUBKEY_LENGTH);
|
||||
if (keylen == ED25519_SEED_LENGTH) {
|
||||
// Using a seed
|
||||
RHash *ctx = r_hash_new (true, R_HASH_SHA512);
|
||||
r_hash_do_sha512 (ctx, key, keylen);
|
||||
keylen = 64;
|
||||
cj->key = calloc (1, keylen);
|
||||
memcpy (cj->key, ctx->digest, keylen);
|
||||
r_hash_free (ctx);
|
||||
} else if (keylen == 64) {
|
||||
keylen = ED25519_PRIVKEY_LENGTH;
|
||||
cj->key = malloc (keylen);
|
||||
ed25519_create_keypair (key, cj->key, (ut8 *)cj->data);
|
||||
} else if (keylen == ED25519_PRIVKEY_LENGTH) {
|
||||
ge_p3 A;
|
||||
memcpy (cj->key, key, keylen);
|
||||
ge_scalarmult_base (&A, cj->key);
|
||||
ge_p3_tobytes (cj->data, &A);
|
||||
}
|
||||
|
||||
cj->key_len = keylen;
|
||||
@ -44,17 +58,13 @@ static bool ed25519_use(const char *algo) {
|
||||
}
|
||||
|
||||
static bool update(RCryptoJob *cj, const ut8 *buf, int len) {
|
||||
ut8 public_key[32] = { 0 };
|
||||
ut8 *public_key = (ut8 *)cj->data;
|
||||
ut8 r[64];
|
||||
ge_p3 R;
|
||||
ge_p3 A;
|
||||
ut8 signature[64] = { 0 };
|
||||
|
||||
// Signature (R, S)
|
||||
if (cj->dir == R_CRYPTO_DIR_ENCRYPT) {
|
||||
// Compute public key
|
||||
ge_scalarmult_base(&A, cj->key);
|
||||
ge_p3_tobytes (public_key, &A);
|
||||
// r = H( cj->key[32:64] || buf)
|
||||
RHash *ctx = r_hash_new (true, R_HASH_SHA512);
|
||||
r_sha512_init (&ctx->sha512);
|
||||
|
19
libr/include/r_crypto/r_ed25519.h
Normal file
19
libr/include/r_crypto/r_ed25519.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef R_ED25519_H
|
||||
#define R_ED25519_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ED25519_SIG_LEN 64
|
||||
#define ED25519_SEED_LENGTH 32
|
||||
#define ED25519_PUBKEY_LENGTH 32
|
||||
#define ED25519_PRIVKEY_LENGTH 64
|
||||
|
||||
R_API void ed25519_create_keypair(const ut8 *seed, ut8 *privkey, ut8 *pubkey);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // R_ED25519_H
|
@ -22,7 +22,8 @@ enum {
|
||||
R_SEARCH_XREFS,
|
||||
R_SEARCH_AES,
|
||||
R_SEARCH_SM4,
|
||||
R_SEARCH_PRIV_KEY,
|
||||
R_SEARCH_ASN1_PRIV_KEY,
|
||||
R_SEARCH_RAW_PRIV_KEY,
|
||||
R_SEARCH_DELTAKEY,
|
||||
R_SEARCH_MAGIC,
|
||||
R_SEARCH_RABIN_KARP,
|
||||
|
@ -543,6 +543,7 @@ install_headers(r_util_files, install_dir: join_paths(r2_incdir, 'r_util'))
|
||||
r_crypto_files = [
|
||||
'include/r_crypto/r_aes.h',
|
||||
'include/r_crypto/r_des.h',
|
||||
'include/r_crypto/r_ed25519.h',
|
||||
'include/r_crypto/r_sm4.h'
|
||||
]
|
||||
install_headers(r_crypto_files, install_dir: join_paths(r2_incdir, 'r_crypto'))
|
||||
|
@ -15,7 +15,7 @@ r_search_sources = [
|
||||
r_search = library('r_search', r_search_sources,
|
||||
include_directories: [platform_inc],
|
||||
c_args: library_cflags,
|
||||
dependencies: [r_util_dep],
|
||||
dependencies: [r_crypto_dep, r_util_dep],
|
||||
install: true,
|
||||
implicit_include_directories: false,
|
||||
install_rpath: rpath_lib,
|
||||
|
@ -4,12 +4,15 @@
|
||||
// Integrated and refactored by jvoisin and spelissier
|
||||
|
||||
#include <r_search.h>
|
||||
#include <r_crypto/r_ed25519.h>
|
||||
|
||||
/* The minimal length to perform a search is the sizes of
|
||||
the sequence tag, the minimal length of the sequence,
|
||||
the version marker and the minimal key length. */
|
||||
#define PRIVKEY_SEARCH_MIN_LENGTH (1 + 1 + 4 + 1)
|
||||
|
||||
#define ED25519_SEARCH_MIN_LENGTH ED25519_PRIVKEY_LENGTH
|
||||
|
||||
/*Baby BER parser, just good enough for private keys.
|
||||
|
||||
This is not robust to errors in the memory image, but if we added
|
||||
@ -64,7 +67,7 @@ static int check_fields(const ut8 *start) {
|
||||
// Finds and return index of a private key:
|
||||
// As defined in RFC 3447 for RSA, as defined in RFC 5915 for
|
||||
// elliptic curves and as defined in 7 of RFC 8410 for SafeCurves
|
||||
R_IPI int search_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len) {
|
||||
R_IPI int search_asn1_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len) {
|
||||
int i, k, max, index, t;
|
||||
RListIter *iter;
|
||||
RSearchKeyword *kw;
|
||||
@ -116,3 +119,41 @@ R_IPI int search_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void hexprint(const ut8 *data, int len) {
|
||||
int i = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
r_cons_printf ("%02x", data[i]);
|
||||
}
|
||||
r_cons_newline ();
|
||||
}
|
||||
|
||||
// Finds and return index of a private key matching a given public key.
|
||||
R_IPI int search_raw_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len) {
|
||||
int t, i;
|
||||
RSearchKeyword *kw;
|
||||
RListIter *iter;
|
||||
const size_t old_nhits = s->nhits;
|
||||
ut8 public_key[ED25519_PUBKEY_LENGTH] = { 0 };
|
||||
ut8 private_key[ED25519_PRIVKEY_LENGTH] = { 0 };
|
||||
ut8 public_key_target[ED25519_PUBKEY_LENGTH] = { 0 };
|
||||
|
||||
if (len < ED25519_SEARCH_MIN_LENGTH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
r_hex_str2bin ((char *)s->data, public_key_target);
|
||||
|
||||
r_list_foreach (s->kws, iter, kw) {
|
||||
for (i = 0; i < len - ED25519_SEARCH_MIN_LENGTH; i++) {
|
||||
ed25519_create_keypair (buf + i, private_key, public_key);
|
||||
if (!memcmp (public_key, public_key_target, ED25519_PUBKEY_LENGTH)) {
|
||||
t = r_search_hit_new (s, kw, from + i);
|
||||
if (t > 1) {
|
||||
return s->nhits - old_nhits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -86,7 +86,8 @@ R_API int r_search_set_mode(RSearch *s, int mode) {
|
||||
case R_SEARCH_REGEXP: s->update = search_regexp_update; break;
|
||||
case R_SEARCH_AES: s->update = search_aes_update; break;
|
||||
case R_SEARCH_SM4: s->update = search_sm4_update; break;
|
||||
case R_SEARCH_PRIV_KEY: s->update = search_privkey_update; break;
|
||||
case R_SEARCH_ASN1_PRIV_KEY: s->update = search_asn1_privkey_update; break;
|
||||
case R_SEARCH_RAW_PRIV_KEY: s->update = search_raw_privkey_update; break;
|
||||
case R_SEARCH_STRING: s->update = search_strings_update; break;
|
||||
case R_SEARCH_DELTAKEY: s->update = search_deltakey_update; break;
|
||||
case R_SEARCH_MAGIC: s->update = search_magic_update; break;
|
||||
|
@ -2,7 +2,8 @@
|
||||
R_IPI int search_kw_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_aes_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_sm4_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_asn1_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_raw_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_deltakey_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_strings_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_regexp_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
|
@ -95,3 +95,14 @@ EXPECT=<<EOF
|
||||
0x00117060 hit4_0 d978f9c419ddb5ed28e9fd794aa0d89dc67e37832b76538e624c6488448bfba2
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=cmd.hit for /cp ed25519
|
||||
FILE=-
|
||||
CMDS=<<EOF
|
||||
wx 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60 @ 423
|
||||
/cp ed25519 d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x000001a7 hit0_0 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
|
||||
EOF
|
||||
RUN
|
||||
|
Loading…
x
Reference in New Issue
Block a user