Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
2db97986
Commit
2db97986
authored
Oct 06, 2015
by
Gustav Simonsson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
common, crypto: add ICAP functions
parent
44fd3951
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
314 additions
and
0 deletions
+314
-0
big.go
common/big.go
+3
-0
icap.go
common/icap.go
+190
-0
icap_test.go
common/icap_test.go
+91
-0
key.go
crypto/key.go
+22
-0
key_store_test.go
crypto/key_store_test.go
+8
-0
No files found.
common/big.go
View file @
2db97986
...
@@ -27,6 +27,9 @@ var (
...
@@ -27,6 +27,9 @@ var (
BigTrue
=
Big1
BigTrue
=
Big1
BigFalse
=
Big0
BigFalse
=
Big0
Big32
=
big
.
NewInt
(
32
)
Big32
=
big
.
NewInt
(
32
)
Big36
=
big
.
NewInt
(
36
)
Big97
=
big
.
NewInt
(
97
)
Big98
=
big
.
NewInt
(
98
)
Big256
=
big
.
NewInt
(
0xff
)
Big256
=
big
.
NewInt
(
0xff
)
Big257
=
big
.
NewInt
(
257
)
Big257
=
big
.
NewInt
(
257
)
MaxBig
=
String2Big
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
)
MaxBig
=
String2Big
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
)
...
...
common/icap.go
0 → 100644
View file @
2db97986
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Spec at https://github.com/ethereum/wiki/wiki/ICAP:-Inter-exchange-Client-Address-Protocol
package
common
import
(
"errors"
"math/big"
"strconv"
"strings"
)
var
(
Base36Chars
=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ICAPLengthError
=
errors
.
New
(
"Invalid ICAP length"
)
ICAPEncodingError
=
errors
.
New
(
"Invalid ICAP encoding"
)
ICAPChecksumError
=
errors
.
New
(
"Invalid ICAP checksum"
)
ICAPCountryCodeError
=
errors
.
New
(
"Invalid ICAP country code"
)
ICAPAssetIdentError
=
errors
.
New
(
"Invalid ICAP asset identifier"
)
ICAPInstCodeError
=
errors
.
New
(
"Invalid ICAP institution code"
)
ICAPClientIdentError
=
errors
.
New
(
"Invalid ICAP client identifier"
)
)
func
ICAPToAddress
(
s
string
)
(
Address
,
error
)
{
switch
len
(
s
)
{
case
35
:
// "XE" + 2 digit checksum + 31 base-36 chars of address
return
parseICAP
(
s
)
case
34
:
// "XE" + 2 digit checksum + 30 base-36 chars of address
return
parseICAP
(
s
)
case
20
:
// "XE" + 2 digit checksum + 3-char asset identifier +
// 4-char institution identifier + 9-char institution client identifier
return
parseIndirectICAP
(
s
)
default
:
return
Address
{},
ICAPLengthError
}
}
func
parseICAP
(
s
string
)
(
Address
,
error
)
{
if
!
strings
.
HasPrefix
(
s
,
"XE"
)
{
return
Address
{},
ICAPCountryCodeError
}
if
err
:=
validCheckSum
(
s
);
err
!=
nil
{
return
Address
{},
err
}
// checksum is ISO13616, Ethereum address is base-36
bigAddr
,
_
:=
new
(
big
.
Int
)
.
SetString
(
s
[
4
:
],
36
)
return
BigToAddress
(
bigAddr
),
nil
}
func
parseIndirectICAP
(
s
string
)
(
Address
,
error
)
{
if
!
strings
.
HasPrefix
(
s
,
"XE"
)
{
return
Address
{},
ICAPCountryCodeError
}
if
s
[
4
:
7
]
!=
"ETH"
{
return
Address
{},
ICAPAssetIdentError
}
if
err
:=
validCheckSum
(
s
);
err
!=
nil
{
return
Address
{},
err
}
// TODO: integrate with ICAP namereg
return
Address
{},
errors
.
New
(
"not implemented"
)
}
func
AddressToICAP
(
a
Address
)
(
string
,
error
)
{
enc
:=
base36Encode
(
a
.
Big
())
// zero padd encoded address to Direct ICAP length if needed
if
len
(
enc
)
<
30
{
enc
=
join
(
strings
.
Repeat
(
"0"
,
30
-
len
(
enc
)),
enc
)
}
icap
:=
join
(
"XE"
,
checkDigits
(
enc
),
enc
)
return
icap
,
nil
}
// TODO: integrate with ICAP namereg when it's available
func
AddressToIndirectICAP
(
a
Address
,
instCode
string
)
(
string
,
error
)
{
// return addressToIndirectICAP(a, instCode)
return
""
,
errors
.
New
(
"not implemented"
)
}
func
addressToIndirectICAP
(
a
Address
,
instCode
string
)
(
string
,
error
)
{
// TODO: add addressToClientIdent which grabs client ident from ICAP namereg
//clientIdent := addressToClientIdent(a)
clientIdent
:=
"todo"
return
clientIdentToIndirectICAP
(
instCode
,
clientIdent
)
}
func
clientIdentToIndirectICAP
(
instCode
,
clientIdent
string
)
(
string
,
error
)
{
if
len
(
instCode
)
!=
4
||
!
validBase36
(
instCode
)
{
return
""
,
ICAPInstCodeError
}
if
len
(
clientIdent
)
!=
9
||
!
validBase36
(
instCode
)
{
return
""
,
ICAPClientIdentError
}
// currently ETH is only valid asset identifier
s
:=
join
(
"ETH"
,
instCode
,
clientIdent
)
return
join
(
"XE"
,
checkDigits
(
s
),
s
),
nil
}
// https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
func
validCheckSum
(
s
string
)
error
{
s
=
join
(
s
[
4
:
],
s
[
:
4
])
expanded
,
err
:=
iso13616Expand
(
s
)
if
err
!=
nil
{
return
err
}
checkSumNum
,
_
:=
new
(
big
.
Int
)
.
SetString
(
expanded
,
10
)
if
checkSumNum
.
Mod
(
checkSumNum
,
Big97
)
.
Cmp
(
Big1
)
!=
0
{
return
ICAPChecksumError
}
return
nil
}
func
checkDigits
(
s
string
)
string
{
expanded
,
_
:=
iso13616Expand
(
strings
.
Join
([]
string
{
s
,
"XE00"
},
""
))
num
,
_
:=
new
(
big
.
Int
)
.
SetString
(
expanded
,
10
)
num
.
Sub
(
Big98
,
num
.
Mod
(
num
,
Big97
))
checkDigits
:=
num
.
String
()
// zero padd checksum
if
len
(
checkDigits
)
==
1
{
checkDigits
=
join
(
"0"
,
checkDigits
)
}
return
checkDigits
}
// not base-36, but expansion to decimal literal: A = 10, B = 11, ... Z = 35
func
iso13616Expand
(
s
string
)
(
string
,
error
)
{
var
parts
[]
string
if
!
validBase36
(
s
)
{
return
""
,
ICAPEncodingError
}
for
_
,
c
:=
range
s
{
i
:=
uint64
(
c
)
if
i
>=
65
{
parts
=
append
(
parts
,
strconv
.
FormatUint
(
uint64
(
c
)
-
55
,
10
))
}
else
{
parts
=
append
(
parts
,
string
(
c
))
}
}
return
join
(
parts
...
),
nil
}
func
base36Encode
(
i
*
big
.
Int
)
string
{
var
chars
[]
rune
x
:=
new
(
big
.
Int
)
for
{
x
.
Mod
(
i
,
Big36
)
chars
=
append
(
chars
,
rune
(
Base36Chars
[
x
.
Uint64
()]))
i
.
Div
(
i
,
Big36
)
if
i
.
Cmp
(
Big0
)
==
0
{
break
}
}
// reverse slice
for
i
,
j
:=
0
,
len
(
chars
)
-
1
;
i
<
j
;
i
,
j
=
i
+
1
,
j
-
1
{
chars
[
i
],
chars
[
j
]
=
chars
[
j
],
chars
[
i
]
}
return
string
(
chars
)
}
func
validBase36
(
s
string
)
bool
{
for
_
,
c
:=
range
s
{
i
:=
uint64
(
c
)
// 0-9 or A-Z
if
i
<
48
||
(
i
>
57
&&
i
<
65
)
||
i
>
90
{
return
false
}
}
return
true
}
func
join
(
s
...
string
)
string
{
return
strings
.
Join
(
s
,
""
)
}
common/icap_test.go
0 → 100644
View file @
2db97986
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
common
import
"testing"
/* More test vectors:
https://github.com/ethereum/web3.js/blob/master/test/iban.fromAddress.js
https://github.com/ethereum/web3.js/blob/master/test/iban.toAddress.js
https://github.com/ethereum/web3.js/blob/master/test/iban.isValid.js
https://github.com/ethereum/libethereum/blob/develop/test/libethcore/icap.cpp
*/
type
icapTest
struct
{
name
string
addr
string
icap
string
}
var
icapOKTests
=
[]
icapTest
{
{
"Direct1"
,
"0x52dc504a422f0e2a9e7632a34a50f1a82f8224c7"
,
"XE499OG1EH8ZZI0KXC6N83EKGT1BM97P2O7"
},
{
"Direct2"
,
"0x11c5496aee77c1ba1f0854206a26dda82a81d6d8"
,
"XE1222Q908LN1QBBU6XUQSO1OHWJIOS46OO"
},
{
"DirectZeroPrefix"
,
"0x00c5496aee77c1ba1f0854206a26dda82a81d6d8"
,
"XE7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS"
},
{
"DirectDoubleZeroPrefix"
,
"0x0000a5327eab78357cbf2ae8f3d49fd9d90c7d22"
,
"XE0600DQK33XDTYUCRI0KYM5ELAKXDWWF6"
},
}
var
icapInvalidTests
=
[]
icapTest
{
{
"DirectInvalidCheckSum"
,
""
,
"XE7438O073KYGTWWZN0F2WZ0R8PX5ZPPZS"
},
{
"DirectInvalidCountryCode"
,
""
,
"XD7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS"
},
{
"DirectInvalidLength36"
,
""
,
"XE499OG1EH8ZZI0KXC6N83EKGT1BM97P2O77"
},
{
"DirectInvalidLength33"
,
""
,
"XE499OG1EH8ZZI0KXC6N83EKGT1BM97P2"
},
{
"IndirectInvalidCheckSum"
,
""
,
"XE35ETHXREGGOPHERSSS"
},
{
"IndirectInvalidAssetIdentifier"
,
""
,
"XE34ETHXREGGOPHERSSS"
},
{
"IndirectInvalidLength19"
,
""
,
"XE34ETHXREGGOPHERSS"
},
{
"IndirectInvalidLength21"
,
""
,
"XE34ETHXREGGOPHERSSSS"
},
}
func
TestICAPOK
(
t
*
testing
.
T
)
{
for
_
,
test
:=
range
icapOKTests
{
decodeEncodeTest
(
HexToAddress
(
test
.
addr
),
test
.
icap
,
t
)
}
}
func
TestICAPInvalid
(
t
*
testing
.
T
)
{
for
_
,
test
:=
range
icapInvalidTests
{
failedDecodingTest
(
test
.
icap
,
t
)
}
}
func
decodeEncodeTest
(
addr0
Address
,
icap0
string
,
t
*
testing
.
T
)
{
icap1
,
err
:=
AddressToICAP
(
addr0
)
if
err
!=
nil
{
t
.
Errorf
(
"ICAP encoding failed: %s"
,
err
)
}
if
icap1
!=
icap0
{
t
.
Errorf
(
"ICAP mismatch: have: %s want: %s"
,
icap1
,
icap0
)
}
addr1
,
err
:=
ICAPToAddress
(
icap0
)
if
err
!=
nil
{
t
.
Errorf
(
"ICAP decoding failed: %s"
,
err
)
}
if
addr1
!=
addr0
{
t
.
Errorf
(
"Address mismatch: have: %x want: %x"
,
addr1
,
addr0
)
}
}
func
failedDecodingTest
(
icap
string
,
t
*
testing
.
T
)
{
addr
,
err
:=
ICAPToAddress
(
icap
)
if
err
==
nil
{
t
.
Errorf
(
"Expected ICAP decoding to fail."
)
}
if
addr
!=
(
Address
{})
{
t
.
Errorf
(
"Expected empty Address on failed ICAP decoding."
)
}
}
crypto/key.go
View file @
2db97986
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"encoding/hex"
"encoding/hex"
"encoding/json"
"encoding/json"
"io"
"io"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/pborman/uuid"
"github.com/pborman/uuid"
...
@@ -143,3 +144,24 @@ func NewKey(rand io.Reader) *Key {
...
@@ -143,3 +144,24 @@ func NewKey(rand io.Reader) *Key {
return
NewKeyFromECDSA
(
privateKeyECDSA
)
return
NewKeyFromECDSA
(
privateKeyECDSA
)
}
}
// generate key whose address fits into < 155 bits so it can fit into
// the Direct ICAP spec. for simplicity and easier compatibility with
// other libs, we retry until the first byte is 0.
func
NewKeyForDirectICAP
(
rand
io
.
Reader
)
*
Key
{
randBytes
:=
make
([]
byte
,
64
)
_
,
err
:=
rand
.
Read
(
randBytes
)
if
err
!=
nil
{
panic
(
"key generation: could not read from random source: "
+
err
.
Error
())
}
reader
:=
bytes
.
NewReader
(
randBytes
)
privateKeyECDSA
,
err
:=
ecdsa
.
GenerateKey
(
S256
(),
reader
)
if
err
!=
nil
{
panic
(
"key generation: ecdsa.GenerateKey failed: "
+
err
.
Error
())
}
key
:=
NewKeyFromECDSA
(
privateKeyECDSA
)
if
!
strings
.
HasPrefix
(
key
.
Address
.
Hex
(),
"0x00"
)
{
return
NewKeyForDirectICAP
(
rand
)
}
return
key
}
crypto/key_store_test.go
View file @
2db97986
...
@@ -20,6 +20,7 @@ import (
...
@@ -20,6 +20,7 @@ import (
"encoding/hex"
"encoding/hex"
"fmt"
"fmt"
"reflect"
"reflect"
"strings"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -223,3 +224,10 @@ func loadKeyStoreTestV1(file string, t *testing.T) map[string]KeyStoreTestV1 {
...
@@ -223,3 +224,10 @@ func loadKeyStoreTestV1(file string, t *testing.T) map[string]KeyStoreTestV1 {
}
}
return
tests
return
tests
}
}
func
TestKeyForDirectICAP
(
t
*
testing
.
T
)
{
key
:=
NewKeyForDirectICAP
(
randentropy
.
Reader
)
if
!
strings
.
HasPrefix
(
key
.
Address
.
Hex
(),
"0x00"
)
{
t
.
Errorf
(
"Expected first address byte to be zero, have: %s"
,
key
.
Address
.
Hex
())
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment