|
#!/usr/bin/perl |
|
#BEGIN { if (-e $ENV{SITE}.'/lib') { use lib $ENV{SITE}.'/lib'; } } |
|
|
|
# usage: |
|
# ipfs key export -o /dev/stdout DPKI | perl DHkeys.pl $pku |
|
|
|
# header: 08011240 |
|
# ipfs key list -l --ipns-base base16 | grep self |
|
# pub-self: f01721220d4ca21fd67b197375c10392f392adc4cd33fbce4575d435e23a664f0cbac60f7 |
|
# ........ 1 2 3 4 5 6 |
|
# ........0123456789.123456789.123456789.123456789.123456789.123456789.123 |
|
# pub-self: f0172002408011220cb574dd68763332e5d19aaf7d229b1f0d1229f1a40cc5a350e66b114145367de |
|
# priv-self: f080112407ee64c96a7746b2115f311f42d3de292ea5997ab84a0ba3d246caffb684f8290 |
|
# cb574dd68763332e5d19aaf7d229b1f0d1229f1a40cc5a350e66b114145367de |
|
|
|
|
|
use MIME::Base64 qw(encode_base64 decode_base64); |
|
use lib '.'; |
|
use botname qw(botname); |
|
|
|
|
|
# ed25519 (2^255 - 19) |
|
my $buf64 = <STDIN>; |
|
my $buf = &decode_base64($buf64); |
|
printf "buf: %s (%dc)\n",unpack('H*',$buf),length($buf); |
|
my $sku = substr($buf,4,32); |
|
my $pku = substr($buf,32+4); |
|
|
|
printf "sku: f%s (%dc)\n",unpack('H*',$sku),length($sku); |
|
printf "pku: f%s (%dc)\n",unpack('H*',$pku),length($pku); |
|
|
|
|
|
my $pubkey = shift || '12D3KooWPW89HLc7Ft1UqZGFUfxqxnAKM6sr6rBNLKkGigLC1iFX'; |
|
my $pubkey_raw = substr(decode_mbase58($pubkey),-32); |
|
printf "pubkey: f%s\n",unpack'H*',$pubkey_raw; |
|
#my $ecdh = &ecsecret($sku,$pubkey_raw); |
|
my $eddh = &edsecret($sku,$pubkey_raw); |
|
my $key = &edkeygen($eddh); |
|
printf "key: f%s\n",unpack'H*',$key; |
|
my $key64 = &encode_base64(pack('H12','002408011240').$key,''); |
|
printf "key64: %s\n",$key64; |
|
printf "privkey: 08011240%s\n",unpack'H*',$key; |
|
|
|
exit $?; |
|
|
|
|
|
sub edsecret(@) { |
|
use Crypt::Ed25519 qw(); # no symbols exported |
|
#my $curve = 'ed25519'; |
|
my $recipient_public_raw = pop; |
|
my $origin_private_raw = shift; |
|
#printf "priv58: %s\n",encode_mbase58($private_raw); |
|
#printf "pub58 : %s\n",encode_mbase58($public_raw); |
|
my ($pko, $sko) = Crypt::Ed25519::generate_keypair $origin_private_raw; |
|
#my $origin_public_raw = Crypt::Ed22519::eddsa_public_key($origin_private_raw); |
|
printf "pko: f%s\n",unpack'H*',$pko; |
|
# fc02c7b8a7d67b07e4d7f788e19f4af0f89631ac23c6641d88292f8769139fc4b270f9eb9d380ada9b507e3e3eb498e6e198e70b779985cc72cf153359ee1cd40 |
|
printf "sko: f%s (%uc)\n",unpack('H*',$sko),length($sko); |
|
$shared_secret = Crypt::Ed25519::key_exchange($recipient_public_raw, $sko); |
|
#printf "edsecret: f%s\n",unpack'H*',$shared_secret; |
|
if (wantarray) { |
|
my $secret58 = &encode_mbase58($shared_secret); |
|
my $origin_public58 = &encode_mbase58($pko); |
|
my $recipient_public58 = &encode_mbase58($recipient_public_raw); |
|
printf "DH(%s,%s) = %s\n",&botname($origin_public58),&botname($recipient_public58),$secret58;; |
|
return ($shared_secret,$public58,$pubkey58); |
|
} else { |
|
return $shared_secret; |
|
} |
|
return $shared_secret; |
|
} |
|
|
|
sub edkeygen($){ |
|
my $secret = shift; |
|
my ($pko, $sko) = Crypt::Ed25519::generate_keypair $secret; |
|
my $key = $secret . $pko; |
|
return $key; |
|
} |
|
|
|
sub ecsecret(@) { |
|
use Crypt::PK::ECC; |
|
our $secrets; |
|
my $curve = 'secp256k1'; |
|
my $public_raw = pop; |
|
my $private_raw = shift; |
|
#printf "priv58: %s\n",encode_mbase58($private_raw); |
|
#printf "pub58 : %s\n",encode_mbase58($public_raw); |
|
|
|
my $sk = Crypt::PK::ECC->new(); |
|
my $priv = $sk->import_key_raw($private_raw, $curve); |
|
my $pk = Crypt::PK::ECC->new(); |
|
my $pub = $pk->import_key_raw($public_raw ,$curve); |
|
my $shared_secret = $priv->shared_secret($pub); |
|
if (wantarray) { |
|
my $secret58 = &encode_mbase58($shared_secret); |
|
my $origin_raw = $priv->export_key_raw('public_compressed'); |
|
my $public58 = &encode_mbase58($origin_raw); |
|
my $pubkey58 = &encode_mbase58($public_raw); |
|
printf "DH(%s,%s) = %s\n",&botname($public58),&botname($pubkey58),$secret58;; |
|
return ($shared_secret,$public58,$pubkey58); |
|
} else { |
|
return $shared_secret; |
|
} |
|
} |
|
|
|
|
|
sub encode_mbase58 { |
|
my $mh = sprintf'z%s',&encode_base58(@_); |
|
return $mh; |
|
} |
|
sub decode_mbase58 { |
|
my $raw; |
|
if ($_[0] =~ m/^z/) { |
|
$raw = decode_base58(substr($_[0],1)); |
|
} else { |
|
$raw = decode_base58($_[0]); |
|
} |
|
return $raw; |
|
} |
|
sub encode_base58 { # btc |
|
use Math::BigInt; |
|
use Encode::Base58::BigInt qw(); |
|
my $bin = join'',@_; |
|
my $bint = Math::BigInt->from_bytes($bin); |
|
my $h58 = Encode::Base58::BigInt::encode_base58($bint); |
|
$h58 =~ tr/a-km-zA-HJ-NP-Z/A-HJ-NP-Za-km-z/; # btc |
|
return $h58; |
|
} |
|
sub decode_base58 { |
|
use Carp qw(cluck); |
|
use Math::BigInt; |
|
use Encode::Base58::BigInt qw(); |
|
my $s = $_[0]; |
|
$s =~ tr/A-HJ-NP-Za-km-zIO0l/a-km-zA-HJ-NP-ZiooL/; # btc |
|
$s =~ tr/IO0l/iooL/; # forbidden chars |
|
my $bint = Encode::Base58::BigInt::decode_base58($s); |
|
cluck "error decoding $s!" unless $bint; |
|
my $bin = Math::BigInt->new($bint)->as_bytes(); |
|
return $bin; |
|
} |
|
|
|
# ------------------------------------------------------------------ |
|
1; # |
|
|
|
__DATA__ |
|
syntax = "proto2"; |
|
|
|
enum KeyType { |
|
RSA = 0; |
|
Ed25519 = 1; |
|
Secp256k1 = 2; |
|
ECDSA = 3; |
|
} |
|
|
|
message PublicKey { |
|
required KeyType Type = 1; |
|
required bytes Data = 2; |
|
} |
|
|
|
message PrivateKey { |
|
required KeyType Type = 1; |
|
required bytes Data = 2; |
|
} |
|
__END__ |