File: clitool.c

package info (click to toggle)
libbase58 0.1.4-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 192 kB
  • sloc: ansic: 288; makefile: 35; sh: 32
file content (130 lines) | stat: -rw-r--r-- 2,320 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * Copyright 2014 Luke Dashjr
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the standard MIT license.  See COPYING for more details.
 */

#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <gcrypt.h>

#include "libbase58.h"

static
bool my_sha256(void *digest, const void *data, size_t datasz)
{
	gcry_md_hash_buffer(GCRY_MD_SHA256, digest, data, datasz);
	return true;
}

static
void usage(const char *prog)
{
	fprintf(stderr, "Usage: %s [-c] [-d] [data]\n", prog);
	fprintf(stderr, "\t-c         Use base58check (default: raw base58)\n");
	fprintf(stderr, "\t-d <size>  Decode <size> bytes\n");
	exit(1);
}

int main(int argc, char **argv)
{
	bool b58c = false;
	size_t decode = 0;
	int opt;
	while ( (opt = getopt(argc, argv, "cd:h")) != -1)
	{
		switch (opt)
		{
			case 'c':
				b58c = true;
				b58_sha256_impl = my_sha256;
				break;
			case 'd':
			{
				int i = atoi(optarg);
				if (i < 0 || (uintmax_t)i >= SIZE_MAX)
					usage(argv[0]);
				decode = (size_t)i;
				break;
			}
			default:
				usage(argv[0]);
		}
	}
	
	size_t rt;
	union {
		uint8_t *b;
		char *s;
	} r;
	if (optind >= argc)
	{
		rt = 0;
		r.b = NULL;
		while (!feof(stdin))
		{
			r.b = realloc(r.b, rt + 0x100);
			rt += fread(&r.b[rt], 1, 0x100, stdin);
		}
		if (decode)
			while (isspace(r.s[rt-1]))
				--rt;
	}
	else
	{
		r.s = argv[optind];
		rt = strlen(argv[optind]);
	}
	
	if (decode)
	{
		uint8_t bin[decode];
		size_t ssz = decode;
		if (!b58tobin(bin, &ssz, r.s, rt))
			return 2;
		if (b58c)
		{
			int chk = b58check(bin, decode, r.s, rt);
			if (chk < 0)
				return chk;
			if (fwrite(bin, decode, 1, stdout) != 1)
				return 3;
		}
		else
		{
			// Raw base58 doesn't check length match
			uint8_t cbin[ssz];
			if (ssz > decode)
			{
				size_t zeros = ssz - decode;
				memset(cbin, 0, zeros);
				memcpy(&cbin[zeros], bin, decode);
			}
			else
				memcpy(cbin, &bin[decode - ssz], ssz);
			
			if (fwrite(cbin, ssz, 1, stdout) != 1)
				return 3;
		}
	}
	else
	{
		size_t ssz = rt * 2;
		char s[ssz];
		bool rv;
		if (b58c)
			rv = rt && b58check_enc(s, &ssz, r.b[0], &r.b[1], rt-1);
		else
			rv = b58enc(s, &ssz, r.b, rt);
		if (!rv)
			return 2;
		puts(s);
	}
}