Example #1
0
void PRE_IO_file2rekey(PRE_REKEY *rekey,EC_GROUP *G,char *file)
{
	FILE *fp;
	if( NULL == (fp = fopen( file,"rb")) )exit(1);

	BN_CTX *ctx = BN_CTX_new();
	/*Read order
	 * v->U->W
	 */
	int strlenOfV = 0;
	int strlenOfU = 0;
	int strlenOfW = 0;
	fread(&strlenOfV,sizeOfInt,1,fp);
	fread(&strlenOfU,sizeOfInt,1,fp);
	fread(&strlenOfW,sizeOfInt,1,fp);
	char *v = (char*)OPENSSL_malloc(strlenOfV);
	char *U = (char*)OPENSSL_malloc(strlenOfU);
	char *W = (char*)OPENSSL_malloc(strlenOfW);
	fread(v,strlenOfV,1,fp);
	fread(U,strlenOfU,1,fp);
	fread(W,strlenOfW,1,fp);

	BN_hex2bn(&rekey->v,v);
	EC_POINT_hex2point(G,U,rekey->U,ctx);
	EC_POINT_hex2point(G,W,rekey->W,ctx);

	BN_CTX_free(ctx);
	fclose(fp);
}
polypseud_ctx *polypseud_ctx_new() {
    polypseud_ctx *ctx = (polypseud_ctx*)malloc(sizeof(polypseud_ctx));
    ctx->bn_ctx = BN_CTX_new();
    ctx->p = BN_new();
    ctx->a = BN_new();
    ctx->b = BN_new();
    BN_hex2bn(&ctx->p, "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27");
    BN_hex2bn(&ctx->a, "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4");
    BN_hex2bn(&ctx->b, "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6");
    ctx->ec_group = EC_GROUP_new_curve_GFp(ctx->p, ctx->a, ctx->b, ctx->bn_ctx);
    if(ctx->ec_group == NULL) {
        BN_free(ctx->p);
        BN_free(ctx->a);
        BN_free(ctx->b);
        BN_CTX_free(ctx->bn_ctx);
        return NULL;
    }
    ctx->q = BN_new();
    BN_hex2bn(&ctx->q, "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311");
    ctx->g = EC_POINT_new(ctx->ec_group);
    EC_POINT_hex2point(ctx->ec_group,
            "0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
            ctx->g, ctx->bn_ctx);
    EC_GROUP_set_generator(ctx->ec_group, ctx->g, ctx->q, BN_value_one());
    return ctx;
}
Example #3
0
void PRE_IO_file2key(char*filePath,unsigned char **key,PRE_KEY *key2)
{
	FILE *fp;
	if( NULL == ( fp = fopen(filePath,"rb") ))
		exit(1);

	Cipher_REKEY *C_r = new Cipher_REKEY();
	BN_CTX *ctx = BN_CTX_new();
	/*Read Order:
	 * E->F->U->W
	 */
	int strlenOfE = 0;
	int strlenOfF = 0;
	int strlenOfU = 0;
	int strlenOfW = 0;
	fread(&strlenOfE,sizeOfInt,1,fp);
	fread(&strlenOfF,sizeOfInt,1,fp);
	fread(&strlenOfU,sizeOfInt,1,fp);
	fread(&strlenOfW,sizeOfInt,1,fp);
	C_r->E = (unsigned char*)OPENSSL_malloc(strlenOfE);
	char *F = (char*)OPENSSL_malloc(strlenOfF);
	char *U = (char*)OPENSSL_malloc(strlenOfU);
	char *W = (char*)OPENSSL_malloc(strlenOfW);
	fread(C_r->E,strlenOfE,1,fp);
	fread(F,strlenOfF,1,fp);
	fread(U,strlenOfU,1,fp);
	fread(W,strlenOfW,1,fp);

	EC_POINT_hex2point(params->G,F,C_r->F,ctx);
	EC_POINT_hex2point(params->G,U,C_r->U,ctx);
	EC_POINT_hex2point(params->G,W,C_r->W,ctx);
	*key = Decrypt(key2,C_r);
	BN_CTX_free(ctx);

	fclose(fp);
}
Example #4
0
static workitem_t *
server_workitem_new(server_request_t *reqp,
		    const char *pfx, const char *pubkey_s,
		    const char *addrtype_s, const char *reward_s,
		    const char *comment)
{
	workitem_t *wip;
	EC_POINT *pubkey;
	int addrtype;
	double reward;
	double difficulty;

	addrtype = atoi(addrtype_s);
	if ((addrtype < 0) || (addrtype > 255))
		return NULL;

	reward = strtod(reward_s, NULL);
	if (reward < 0.0)
		return NULL;

	difficulty = vg_prefix_get_difficulty(addrtype, pfx);
	if (difficulty == 0.0)
		return NULL;

	pubkey = EC_POINT_hex2point(reqp->group, pubkey_s, NULL, NULL);
	if (pubkey == NULL)
		return NULL;


	wip = (workitem_t *) malloc(sizeof(*wip) +
				    strlen(pfx) +
				    strlen(comment) + 2);
	memset(wip, 0, sizeof(*wip));
	avl_item_init(&wip->avlent);
	wip->pattern = (char *) (wip + 1);
	strcpy((char *)wip->pattern, pfx);
	wip->comment = wip->pattern + (strlen(wip->pattern) + 1);
	strcpy((char *) wip->comment, comment);
	wip->pubkey = pubkey;
	wip->addrtype = addrtype;
	wip->difficulty = difficulty;
	wip->reward = reward;
	wip->value = (reward * 1000000000.0) / difficulty;

	return wip;
}
Example #5
0
int VNEcdsa_ORG_LoadPubKey( VNAsymCryptCtx_t * ctx,
	const struct vn_iovec * hexPubKey )
{
	EC_POINT * point = NULL;

	VNEcdsa_ORG_Ctx_t * orgCtx = VN_CONTAINER_OF( ctx, VNEcdsa_ORG_Ctx_t, mCtx );
	assert( VN_TYPE_VNEcdsaSign_ORG == ctx->mType );

	point = EC_POINT_new( EC_KEY_get0_group( orgCtx->mEcKey ) );

	EC_POINT_hex2point( EC_KEY_get0_group( orgCtx->mEcKey ), hexPubKey->i.iov_base,
		point, NULL );

	EC_KEY_set_public_key( orgCtx->mEcKey, point );

	EC_POINT_free( point );

	return 0;
}
Example #6
0
int
main(int argc, char **argv)
{
	int addrtype = 0;
	int privtype = 128;
	int regex = 0;
	int caseinsensitive = 0;
	int opt;
	char pwbuf[128];
	int platformidx = -1, deviceidx = -1;
	int prompt_password = 0;
	char *seedfile = NULL;
	char **patterns, *pend;
	int verbose = 1;
	int npatterns = 0;
	int nthreads = 0;
	int worksize = 0;
	int nrows = 0, ncols = 0;
	int invsize = 0;
	int remove_on_match = 1;
	int only_one = 0;
	int verify_mode = 0;
	int safe_mode = 0;
	vg_context_t *vcp = NULL;
	vg_ocl_context_t *vocp = NULL;
	EC_POINT *pubkey_base = NULL;
	const char *result_file = NULL;
	const char *key_password = NULL;
	char *devstrs[MAX_DEVS];
	int ndevstrs = 0;
	int opened = 0;

	FILE *pattfp[MAX_FILE], *fp;
	int pattfpi[MAX_FILE];
	int npattfp = 0;
	int pattstdin = 0;

	int i;

	while ((opt = getopt(argc, argv,
			     "vqik1NTX:Y:eE:p:P:d:w:t:g:b:VSh?f:o:s:D:")) != -1) {
		switch (opt) {
		case 'v':
			verbose = 2;
			break;
		case 'q':
			verbose = 0;
			break;
		case 'i':
			caseinsensitive = 1;
			break;
		case 'k':
			remove_on_match = 0;
			break;
		case '1':
			only_one = 1;
			break;
		case 'N':
			addrtype = 52;
			privtype = 180;
			break;
		case 'T':
			addrtype = 111;
			privtype = 239;
			break;
		case 'X':
			addrtype = atoi(optarg);
			privtype = 128 + addrtype;
			break;
		case 'Y':
			/* Overrides privtype of 'X' but leaves all else intact */
			privtype = atoi(optarg);
			break;
		case 'e':
			prompt_password = 1;
			break;
		case 'E':
			key_password = optarg;
			break;
		case 'p':
			platformidx = atoi(optarg);
			break;
		case 'd':
			deviceidx = atoi(optarg);
			break;
		case 'w':
			worksize = atoi(optarg);
			if (worksize == 0) {
				fprintf(stderr,
					"Invalid work size '%s'\n", optarg);
				return 1;
			}
			break;
		case 't':
			nthreads = atoi(optarg);
			if (nthreads == 0) {
				fprintf(stderr,
					"Invalid thread count '%s'\n", optarg);
				return 1;
			}
			break;
		case 'g':
			nrows = 0;
			ncols = strtol(optarg, &pend, 0);
			if (pend && *pend == 'x') {
				nrows = strtol(pend+1, NULL, 0);
			}
			if (!nrows || !ncols) {
				fprintf(stderr,
					"Invalid grid size '%s'\n", optarg);
				return 1;
			}
			break;
		case 'b':
			invsize = atoi(optarg);
			if (!invsize) {
				fprintf(stderr,
					"Invalid modular inverse size '%s'\n",
					optarg);
				return 1;
			}
			if (invsize & (invsize - 1)) {
				fprintf(stderr,
					"Modular inverse size must be "
					"a power of 2\n");
				return 1;
			}
			break;
		case 'V':
			verify_mode = 1;
			break;
		case 'S':
			safe_mode = 1;
			break;
		case 'D':
			if (ndevstrs >= MAX_DEVS) {
				fprintf(stderr,
					"Too many OpenCL devices (limit %d)\n",
					MAX_DEVS);
				return 1;
			}
			devstrs[ndevstrs++] = optarg;
			break;
		case 'P': {
			if (pubkey_base != NULL) {
				fprintf(stderr,
					"Multiple base pubkeys specified\n");
				return 1;
			}
			EC_KEY *pkey = vg_exec_context_new_key();
			pubkey_base = EC_POINT_hex2point(
				EC_KEY_get0_group(pkey),
				optarg, NULL, NULL);
			EC_KEY_free(pkey);
			if (pubkey_base == NULL) {
				fprintf(stderr,
					"Invalid base pubkey\n");
				return 1;
			}
			break;
		}
		case 'f':
			if (npattfp >= MAX_FILE) {
				fprintf(stderr,
					"Too many input files specified\n");
				return 1;
			}
			if (!strcmp(optarg, "-")) {
				if (pattstdin) {
					fprintf(stderr, "ERROR: stdin "
						"specified multiple times\n");
					return 1;
				}
				fp = stdin;
			} else {
				fp = fopen(optarg, "r");
				if (!fp) {
					fprintf(stderr,
						"Could not open %s: %s\n",
						optarg, strerror(errno));
					return 1;
				}
			}
			pattfp[npattfp] = fp;
			pattfpi[npattfp] = caseinsensitive;
			npattfp++;
			break;
		case 'o':
			if (result_file) {
				fprintf(stderr,
					"Multiple output files specified\n");
				return 1;
			}
			result_file = optarg;
			break;
		case 's':
			if (seedfile != NULL) {
				fprintf(stderr,
					"Multiple RNG seeds specified\n");
				return 1;
			}
			seedfile = optarg;
			break;
		default:
			usage(argv[0]);
			return 1;
		}
	}

#if OPENSSL_VERSION_NUMBER < 0x10000000L
	/* Complain about older versions of OpenSSL */
	if (verbose > 0) {
		fprintf(stderr,
			"WARNING: Built with " OPENSSL_VERSION_TEXT "\n"
			"WARNING: Use OpenSSL 1.0.0d+ for best performance\n");
	}
#endif

	if (caseinsensitive && regex)
		fprintf(stderr,
			"WARNING: case insensitive mode incompatible with "
			"regular expressions\n");

	if (seedfile) {
		opt = -1;
#if !defined(_WIN32)
		{	struct stat st;
			if (!stat(seedfile, &st) &&
			    (st.st_mode & (S_IFBLK|S_IFCHR))) {
				opt = 32;
		} }
#endif
		opt = RAND_load_file(seedfile, opt);
		if (!opt) {
			fprintf(stderr, "Could not load RNG seed %s\n", optarg);
			return 1;
		}
		if (verbose > 0) {
			fprintf(stderr,
				"Read %d bytes from RNG seed file\n", opt);
		}
	}

	if (regex) {
		vcp = vg_regex_context_new(addrtype, privtype);

	} else {
		vcp = vg_prefix_context_new(addrtype, privtype,
					    caseinsensitive);
	}

	vcp->vc_verbose = verbose;
	vcp->vc_result_file = result_file;
	vcp->vc_remove_on_match = remove_on_match;
	vcp->vc_only_one = only_one;
	vcp->vc_pubkeytype = addrtype;
	vcp->vc_pubkey_base = pubkey_base;

	vcp->vc_output_match = vg_output_match_console;
	vcp->vc_output_timing = vg_output_timing_console;

	if (!npattfp) {
		if (optind >= argc) {
			usage(argv[0]);
			return 1;
		}
		patterns = &argv[optind];
		npatterns = argc - optind;

		if (!vg_context_add_patterns(vcp,
					     (const char ** const) patterns,
					     npatterns))
		return 1;
	}

	for (i = 0; i < npattfp; i++) {
		fp = pattfp[i];
		if (!vg_read_file(fp, &patterns, &npatterns)) {
			fprintf(stderr, "Failed to load pattern file\n");
			return 1;
		}
		if (fp != stdin)
			fclose(fp);

		if (!regex)
			vg_prefix_context_set_case_insensitive(vcp, pattfpi[i]);

		if (!vg_context_add_patterns(vcp,
					     (const char ** const) patterns,
					     npatterns))
		return 1;
	}

	if (!vcp->vc_npatterns) {
		fprintf(stderr, "No patterns to search\n");
		return 1;
	}

	if (prompt_password) {
		if (!vg_read_password(pwbuf, sizeof(pwbuf)))
			return 1;
		key_password = pwbuf;
	}
	vcp->vc_key_protect_pass = key_password;
	if (key_password) {
		if (!vg_check_password_complexity(key_password, verbose))
			fprintf(stderr,
				"WARNING: Protecting private keys with "
				"weak password\n");
	}

	if ((verbose > 0) && regex && (vcp->vc_npatterns > 1))
		fprintf(stderr,
			"Regular expressions: %ld\n", vcp->vc_npatterns);

	if (ndevstrs) {
		for (opt = 0; opt < ndevstrs; opt++) {
			vocp = vg_ocl_context_new_from_devstr(vcp, devstrs[opt],
							      safe_mode,
							      verify_mode);
			if (!vocp) {
				fprintf(stderr,
				"Could not open device '%s', ignoring\n",
					devstrs[opt]);
			} else {
				opened++;
			}
		}
	} else {
		vocp = vg_ocl_context_new(vcp, platformidx, deviceidx,
					  safe_mode, verify_mode,
					  worksize, nthreads,
					  nrows, ncols, invsize);
		if (vocp)
			opened++;
	}

	if (!opened) {
		vg_ocl_enumerate_devices();
		return 1;
	}

	opt = vg_context_start_threads(vcp);
	if (opt)
		return 1;

	vg_context_wait_for_completion(vcp);
	vg_ocl_context_free(vocp);
	return 0;
}
int
main(int argc, char **argv)
{
	int addrtype = 0;
	int scriptaddrtype = 5;
	int privtype = 128;
	int pubkeytype;
	enum vg_format format = VCF_PUBKEY;
	int regex = 0;
	int caseinsensitive = 0;
	int verbose = 1;
	int simulate = 0;
	int remove_on_match = 1;
	int only_one = 0;
	int prompt_password = 0;
	int opt;
	char *seedfile = NULL;
	char pwbuf[128];
	const char *result_file = NULL;
	const char *key_password = NULL;
	char **patterns;
	int npatterns = 0;
	int nthreads = 0;
	vg_context_t *vcp = NULL;
	EC_POINT *pubkey_base = NULL;

	FILE *pattfp[MAX_FILE], *fp;
	int pattfpi[MAX_FILE];
	int npattfp = 0;
	int pattstdin = 0;

	int i;

	while ((opt = getopt(argc, argv, "vqnrik1eE:P:WTX:F:t:h?f:o:s:")) != -1) {
		switch (opt) {
		case 'v':
			verbose = 2;
			break;
		case 'q':
			verbose = 0;
			break;
		case 'n':
			simulate = 1;
			break;
		case 'r':
			regex = 1;
			break;
		case 'i':
			caseinsensitive = 1;
			break;
		case 'k':
			remove_on_match = 0;
			break;
		case '1':
			only_one = 1;
			break;
		case 'W':
			addrtype = 73;
			privtype = 201;
			break;
		case 'T':
			addrtype = 111;
			privtype = 239;
			scriptaddrtype = 196;
			break;
		case 'X':
			addrtype = atoi(optarg);
			privtype = 128 + addrtype;
			scriptaddrtype = addrtype;
			break;
		case 'F':
			if (!strcmp(optarg, "script"))
				format = VCF_SCRIPT;
			else
			if (strcmp(optarg, "pubkey")) {
				fprintf(stderr,
					"Invalid format '%s'\n", optarg);
				return 1;
			}
			break;
		case 'P': {
			if (pubkey_base != NULL) {
				fprintf(stderr,
					"Multiple base pubkeys specified\n");
				return 1;
			}
			EC_KEY *pkey = vg_exec_context_new_key();
			pubkey_base = EC_POINT_hex2point(
				EC_KEY_get0_group(pkey),
				optarg, NULL, NULL);
			EC_KEY_free(pkey);
			if (pubkey_base == NULL) {
				fprintf(stderr,
					"Invalid base pubkey\n");
				return 1;
			}
			break;
		}
			
		case 'e':
			prompt_password = 1;
			break;
		case 'E':
			key_password = optarg;
			break;
		case 't':
			nthreads = atoi(optarg);
			if (nthreads == 0) {
				fprintf(stderr,
					"Invalid thread count '%s'\n", optarg);
				return 1;
			}
			break;
		case 'f':
			if (npattfp >= MAX_FILE) {
				fprintf(stderr,
					"Too many input files specified\n");
				return 1;
			}
			if (!strcmp(optarg, "-")) {
				if (pattstdin) {
					fprintf(stderr, "ERROR: stdin "
						"specified multiple times\n");
					return 1;
				}
				fp = stdin;
			} else {
				fp = fopen(optarg, "r");
				if (!fp) {
					fprintf(stderr,
						"Could not open %s: %s\n",
						optarg, strerror(errno));
					return 1;
				}
			}
			pattfp[npattfp] = fp;
			pattfpi[npattfp] = caseinsensitive;
			npattfp++;
			break;
		case 'o':
			if (result_file) {
				fprintf(stderr,
					"Multiple output files specified\n");
				return 1;
			}
			result_file = optarg;
			break;
		case 's':
			if (seedfile != NULL) {
				fprintf(stderr,
					"Multiple RNG seeds specified\n");
				return 1;
			}
			seedfile = optarg;
			break;
		default:
			usage(argv[0]);
			return 1;
		}
	}

#if OPENSSL_VERSION_NUMBER < 0x10000000L
	/* Complain about older versions of OpenSSL */
	if (verbose > 0) {
		fprintf(stderr,
			"WARNING: Built with " OPENSSL_VERSION_TEXT "\n"
			"WARNING: Use OpenSSL 1.0.0d+ for best performance\n");
	}
#endif

	if (caseinsensitive && regex)
		fprintf(stderr,
			"WARNING: case insensitive mode incompatible with "
			"regular expressions\n");

	pubkeytype = addrtype;
	if (format == VCF_SCRIPT)
	{
		if (scriptaddrtype == -1)
		{
			fprintf(stderr,
				"Address type incompatible with script format\n");
			return 1;
		}
		addrtype = scriptaddrtype;
	}

	if (seedfile) {
		opt = -1;
#if !defined(_WIN32)
		{	struct stat st;
			if (!stat(seedfile, &st) &&
			    (st.st_mode & (S_IFBLK|S_IFCHR))) {
				opt = 32;
		} }
#endif
		opt = RAND_load_file(seedfile, opt);
		if (!opt) {
			fprintf(stderr, "Could not load RNG seed %s\n", optarg);
			return 1;
		}
		if (verbose > 0) {
			fprintf(stderr,
				"Read %d bytes from RNG seed file\n", opt);
		}
	}

	if (regex) {
		vcp = vg_regex_context_new(addrtype, privtype);

	} else {
		vcp = vg_prefix_context_new(addrtype, privtype,
					    caseinsensitive);
	}

	vcp->vc_verbose = verbose;
	vcp->vc_result_file = result_file;
	vcp->vc_remove_on_match = remove_on_match;
	vcp->vc_only_one = only_one;
	vcp->vc_format = format;
	vcp->vc_pubkeytype = pubkeytype;
	vcp->vc_pubkey_base = pubkey_base;

	vcp->vc_output_match = vg_output_match_console;
	vcp->vc_output_timing = vg_output_timing_console;

	if (!npattfp) {
		if (optind >= argc) {
			usage(argv[0]);
			return 1;
		}
		patterns = &argv[optind];
		npatterns = argc - optind;

		if (!vg_context_add_patterns(vcp,
					     (const char ** const) patterns,
					     npatterns))
		return 1;
	}

	for (i = 0; i < npattfp; i++) {
		fp = pattfp[i];
		if (!vg_read_file(fp, &patterns, &npatterns)) {
			fprintf(stderr, "Failed to load pattern file\n");
			return 1;
		}
		if (fp != stdin)
			fclose(fp);

		if (!regex)
			vg_prefix_context_set_case_insensitive(vcp, pattfpi[i]);

		if (!vg_context_add_patterns(vcp,
					     (const char ** const) patterns,
					     npatterns))
		return 1;
	}

	if (!vcp->vc_npatterns) {
		fprintf(stderr, "No patterns to search\n");
		return 1;
	}

	if (prompt_password) {
		if (!vg_read_password(pwbuf, sizeof(pwbuf)))
			return 1;
		key_password = pwbuf;
	}
	vcp->vc_key_protect_pass = key_password;
	if (key_password) {
		if (!vg_check_password_complexity(key_password, verbose))
			fprintf(stderr,
				"WARNING: Protecting private keys with "
				"weak password\n");
	}

	if ((verbose > 0) && regex && (vcp->vc_npatterns > 1))
		fprintf(stderr,
			"Regular expressions: %ld\n", vcp->vc_npatterns);

	if (simulate)
		return 0;

	if (!start_threads(vcp, nthreads))
		return 1;
	return 0;
}
Example #8
0
int main(int argc, const char *argv[])
{
	int r;
	int ok = 0;
	char *prog = "ecc";

	
	// libpopt var
	poptContext popt_ctx;
	const char **rest;
	int command = 0;
	char *curve_name = "secp192k1";
	int point_compressed = 0;
	point_conversion_form_t point_form;

	struct poptOption options[] = {
		{"curve-name",		'c', POPT_ARG_STRING, &curve_name, 0,		"elliptic curve name", "NAME"},
		{"point-compressed",	'z', POPT_ARG_NONE, &point_compressed, 0,	"point format, compress or uncompress", NULL},
		{"print-curve",		'p', POPT_ARG_VAL, &command, ECC_PRINT,		"print elliptic curve parameters", NULL},
		{"random-private-key",	 0,  POPT_ARG_VAL, &command, ECC_RAND_SKEY,	"random generate a private key\n", NULL},
		{"random-keypair",	 0,  POPT_ARG_VAL, &command, ECC_RAND_KEYPAIR,	"generate a random key pair\n", NULL},
		{"check-point",		'e', POPT_ARG_VAL, &command, ECC_CHECK_POINT,	"check if point is valid\n", NULL},
		{"point-add",		'a', POPT_ARG_VAL, &command, ECC_ADD,		"elliptic curve point addition", NULL},
		{"point-double",	'b', POPT_ARG_VAL, &command, ECC_DOUBLE,	"elliptic curve point double", NULL},
		{"point-mul",		'x', POPT_ARG_VAL, &command, ECC_MUL,		"k*G", NULL},
		{"point-mul-generator",	'X', POPT_ARG_VAL, &command, ECC_MUL_G,		"elliptic curve point scalar multiply", NULL},
		{"point-invert",	'i', POPT_ARG_VAL, &command, ECC_INVERT,	"elliptic curve point inverse", NULL},
		{"ecdsa-sign",		's', POPT_ARG_VAL, &command, ECC_SIGN,		"ecdsa sign", NULL},
		{"ecdsa-verify",	'v', POPT_ARG_VAL, &command, ECC_VERIFY,	"ecdsa verify", NULL},
		POPT_AUTOHELP
		POPT_TABLEEND
	};

	// openssl var
	EC_GROUP *ec_group = NULL;
	EC_POINT *P = NULL;
	EC_POINT *Q = NULL;
	EC_POINT *R = NULL;
	BIGNUM *k = BN_new();
	BN_CTX *bn_ctx = BN_CTX_new();


	// argument parsing
	popt_ctx = poptGetContext(argv[0], argc, argv, options, 0);
	if ((r = poptGetNextOpt(popt_ctx)) < -1) {
		fprintf(stderr, "%s: bad argument %s: %s\n", argv[0], 
			poptBadOption(popt_ctx, POPT_BADOPTION_NOALIAS), 
			poptStrerror(r));
		goto exit;
	}
	rest = poptGetArgs(popt_ctx);


	// check arguments
	ec_group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve_name));
	if (ec_group == NULL) {
		fprintf(stderr, "%s: unknown curve name\n", prog);
		goto exit;
	}

	P = EC_POINT_new(ec_group);
	Q = EC_POINT_new(ec_group);
	R = EC_POINT_new(ec_group);

	point_form = point_compressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED;

	switch (command) {
	case ECC_PRINT:
		{
		BIGNUM *p = BN_new();
		BIGNUM *a = BN_new();
		BIGNUM *b = BN_new();
		char *generator;
		BIGNUM *order = BN_new();
		BIGNUM *cofactor = BN_new();

		EC_GROUP_get_curve_GFp(ec_group, p, a, b, bn_ctx);
		generator = EC_POINT_point2hex(ec_group, EC_GROUP_get0_generator(ec_group), point_form, bn_ctx);
		EC_GROUP_get_order(ec_group, order, bn_ctx);
		EC_GROUP_get_cofactor(ec_group, cofactor, bn_ctx);
		
		fprintf(stdout, "Name      : %s\n", OBJ_nid2sn(EC_GROUP_get_curve_name(ec_group)));
		fprintf(stdout, "FieldType : %s\n", "PrimeField");
		fprintf(stdout, "Prime     : %s\n", BN_bn2hex(p));
		fprintf(stdout, "A         : %s\n", BN_bn2hex(a));
		fprintf(stdout, "B         : %s\n", BN_bn2hex(b));
		fprintf(stdout, "Generator : %s\n", generator);
		fprintf(stdout, "Order     : %s\n", BN_bn2hex(order));
		fprintf(stdout, "Cofactor  : %s\n", BN_bn2hex(cofactor));

		BN_free(p);
		BN_free(a);
		BN_free(b);
		BN_free(order);
		BN_free(cofactor);

		break;
		}
	case ECC_CHECK_POINT:
		{
		if (!rest) {
			fprintf(stderr, "%s: short of point\n", prog);
			goto exit;
		}
		if (!rest[0]) {
			fprintf(stderr, "%s: short of point\n", prog);
			goto exit;
		}
		if (EC_POINT_hex2point(ec_group, rest[0], P, bn_ctx))
			fprintf(stdout, "ture\n");
		else
			fprintf(stdout, "false\n");
		break;
		}
	case ECC_RAND_SKEY:
		{
		EC_KEY *ec_key = EC_KEY_new();
		EC_KEY_set_group(ec_key, ec_group);
		EC_KEY_generate_key(ec_key);
		fprintf(stdout, "%s\n", BN_bn2hex(EC_KEY_get0_private_key(ec_key)));
		EC_KEY_free(ec_key);
		break;
		}
	case ECC_RAND_KEYPAIR:
		{
		EC_KEY *ec_key = EC_KEY_new();
		EC_KEY_set_group(ec_key, ec_group);
		EC_KEY_generate_key(ec_key);
		fprintf(stdout, "%s\n", BN_bn2hex(EC_KEY_get0_private_key(ec_key)));
		fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, EC_KEY_get0_public_key(ec_key), point_form, bn_ctx));
		EC_KEY_free(ec_key);
		break;
		}
	case ECC_ADD:
		{
		if (!rest) {
			fprintf(stderr, "%s: short of point\n", prog);
			goto exit;
		}
		if (!rest[0] || !rest[1]) {
			fprintf(stderr, "%s: short of point\n", prog);
			goto exit;
		}			
		if (!EC_POINT_hex2point(ec_group, rest[1], P, bn_ctx)) {
			fprintf(stderr, "%s: first point invalid\n", prog);
			goto exit;
		}
		if (!EC_POINT_hex2point(ec_group, rest[1], Q, bn_ctx)) {
			fprintf(stderr, "%s: second point invalid\n", prog);
			goto exit;
		}
		EC_POINT_add(ec_group, R, P, Q, bn_ctx);
		fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx));
		break;
		}
	case ECC_DOUBLE:
		{
		EC_POINT_dbl(ec_group, R, P, bn_ctx);
		fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx));
		break;
		}
	case ECC_MUL:
		{
		BIGNUM *order = NULL;

		if (!BN_hex2bn(&k, rest[0])) {
			fprintf(stderr, "%s: integer invalid\n", prog);
			goto exit;
		}
		
		order = BN_new();
		EC_GROUP_get_order(ec_group, order, bn_ctx);
		if (BN_cmp(k, order) >= 0) {
			fprintf(stderr, "%s: integer value invalid\n", prog);
			BN_free(order);
			goto exit;
		}
		BN_free(order);

		if (!EC_POINT_hex2point(ec_group, rest[1], P, bn_ctx)) {
			fprintf(stderr, "%s: point invalid\n", prog);
			goto exit;
		}

		EC_POINT_mul(ec_group, R, k, P, NULL, bn_ctx);
		fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx));

		break;
		}
	case ECC_MUL_G:
		{
		BIGNUM *order = NULL;
		if (!BN_hex2bn(&k, rest[0])) {
			fprintf(stderr, "%s: integer format invalid\n", prog);
			goto exit;
		}
		
		order = BN_new();
		EC_GROUP_get_order(ec_group, order, bn_ctx);
		if (BN_cmp(k, order) >= 0) {
			fprintf(stderr, "%s: integer value invalid\n", prog);
			BN_free(order);
			goto exit;
		}
		BN_free(order);
		
		EC_POINT_mul(ec_group, R, k, EC_GROUP_get0_generator(ec_group), NULL, bn_ctx);
		fprintf(stdout, "%s\n", EC_POINT_point2hex(ec_group, R, point_form, bn_ctx));
		break;
		}
	default:
		fprintf(stderr, "%s: command is required\n", prog);
		break;
	}
	ok = 1;

exit:
	if (ec_group) EC_GROUP_free(ec_group);
	if (P) EC_POINT_free(P);
	if (k) BN_free(k);
	if (bn_ctx) BN_CTX_free(bn_ctx);

	return ok ? 0 : -1;
}