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
4e52adb8
Commit
4e52adb8
authored
10 years ago
by
zelig
Committed by
Felix Lange
10 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add crypto auth logic to p2p
parent
d227f618
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
174 additions
and
0 deletions
+174
-0
crypto.go
p2p/crypto.go
+174
-0
No files found.
p2p/crypto.go
0 → 100644
View file @
4e52adb8
package
p2p
import
(
"bytes"
"crypto/ecdsa"
"crypto/rand"
"fmt"
"io"
"github.com/ethereum/go-ethereum/crypto"
"github.com/obscuren/ecies"
"github.com/obscuren/secp256k1-go"
)
var
(
skLen
int
=
32
// ecies.MaxSharedKeyLength(pubKey) / 2
sigLen
int
=
32
// elliptic S256
pubKeyLen
int
=
32
// ECDSA
msgLen
int
=
sigLen
+
1
+
pubKeyLen
+
skLen
// 97
)
//, aesSecret, macSecret, egressMac, ingress
type
secretRW
struct
{
aesSecret
,
macSecret
,
egressMac
,
ingressMac
[]
byte
}
type
cryptoId
struct
{
prvKey
*
ecdsa
.
PrivateKey
pubKey
*
ecdsa
.
PublicKey
pubKeyR
io
.
ReaderAt
}
func
newCryptoId
(
id
ClientIdentity
)
(
self
*
cryptoId
,
err
error
)
{
// will be at server init
var
prvKeyDER
[]
byte
=
id
.
PrivKey
()
if
prvKeyDER
==
nil
{
err
=
fmt
.
Errorf
(
"no private key for client"
)
return
}
// initialise ecies private key via importing DER encoded keys (known via our own clientIdentity)
var
prvKey
=
crypto
.
ToECDSA
(
prvKeyDER
)
if
prvKey
==
nil
{
err
=
fmt
.
Errorf
(
"invalid private key for client"
)
return
}
self
=
&
cryptoId
{
prvKey
:
prvKey
,
// initialise public key from the imported private key
pubKey
:
&
prvKey
.
PublicKey
,
// to be created at server init shared between peers and sessions
// for reuse, call wth ReadAt, no reset seek needed
}
self
.
pubKeyR
=
bytes
.
NewReader
(
id
.
Pubkey
())
return
}
//
func
(
self
*
cryptoId
)
setupAuth
(
remotePubKeyDER
,
sessionToken
[]
byte
)
(
auth
[]
byte
,
nonce
[]
byte
,
sharedKnowledge
[]
byte
,
err
error
)
{
// session init, common to both parties
var
remotePubKey
=
crypto
.
ToECDSAPub
(
remotePubKeyDER
)
if
remotePubKey
==
nil
{
err
=
fmt
.
Errorf
(
"invalid remote public key"
)
return
}
var
sharedSecret
[]
byte
// generate shared key from prv and remote pubkey
sharedSecret
,
err
=
ecies
.
ImportECDSA
(
self
.
prvKey
)
.
GenerateShared
(
ecies
.
ImportECDSAPublic
(
remotePubKey
),
skLen
,
skLen
)
if
err
!=
nil
{
return
}
// check previous session token
if
sessionToken
==
nil
{
err
=
fmt
.
Errorf
(
"no session token for peer"
)
return
}
// allocate msgLen long message
var
msg
[]
byte
=
make
([]
byte
,
msgLen
)
// generate skLen long nonce at the end
nonce
=
msg
[
msgLen
-
skLen
:
]
if
_
,
err
=
rand
.
Read
(
nonce
);
err
!=
nil
{
return
}
// create known message
// should use
// cipher.xorBytes from crypto/cipher/xor.go for fast xor
sharedKnowledge
=
Xor
(
sharedSecret
,
sessionToken
)
var
signedMsg
=
Xor
(
sharedKnowledge
,
nonce
)
// generate random keypair to use for signing
var
ecdsaRandomPrvKey
*
ecdsa
.
PrivateKey
if
ecdsaRandomPrvKey
,
err
=
crypto
.
GenerateKey
();
err
!=
nil
{
return
}
// var ecdsaRandomPubKey *ecdsa.PublicKey
// ecdsaRandomPubKey= &ecdsaRandomPrvKey.PublicKey
// message known to both parties ecdh-shared-secret^nonce^token
var
signature
[]
byte
// signature = sign(ecdhe-random, ecdh-shared-secret^nonce^token)
// uses secp256k1.Sign
if
signature
,
err
=
crypto
.
Sign
(
signedMsg
,
ecdsaRandomPrvKey
);
err
!=
nil
{
return
}
// msg = signature || 0x80 || pubk || nonce
copy
(
msg
,
signature
)
msg
[
sigLen
]
=
0x80
self
.
pubKeyR
.
ReadAt
(
msg
[
sigLen
+
1
:
],
int64
(
pubKeyLen
))
// gives pubKeyLen, io.EOF (since we dont read onto the nonce)
// auth = eciesEncrypt(remote-pubk, msg)
if
auth
,
err
=
crypto
.
Encrypt
(
remotePubKey
,
msg
);
err
!=
nil
{
return
}
return
}
func
(
self
*
cryptoId
)
verifyAuth
(
auth
,
nonce
,
sharedKnowledge
[]
byte
)
(
sessionToken
[]
byte
,
rw
*
secretRW
,
err
error
)
{
var
msg
[]
byte
// they prove that msg is meant for me,
// I prove I possess private key if i can read it
if
msg
,
err
=
crypto
.
Decrypt
(
self
.
prvKey
,
auth
);
err
!=
nil
{
return
}
var
remoteNonce
[]
byte
=
msg
[
msgLen
-
skLen
:
]
// I prove that i possess prv key (to derive shared secret, and read nonce off encrypted msg) and that I posessed the earlier one , our shared history
// they prove they possess their private key to derive the same shared secret, plus the same shared history (previous session token)
var
signedMsg
=
Xor
(
sharedKnowledge
,
remoteNonce
)
var
remoteRandomPubKeyDER
[]
byte
if
remoteRandomPubKeyDER
,
err
=
secp256k1
.
RecoverPubkey
(
signedMsg
,
msg
[
:
32
]);
err
!=
nil
{
return
}
var
remoteRandomPubKey
=
crypto
.
ToECDSAPub
(
remoteRandomPubKeyDER
)
if
remoteRandomPubKey
==
nil
{
err
=
fmt
.
Errorf
(
"invalid remote public key"
)
return
}
// 3) Now we can trust ecdhe-random-pubk to derive keys
//ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk)
var
dhSharedSecret
[]
byte
dhSharedSecret
,
err
=
ecies
.
ImportECDSA
(
self
.
prvKey
)
.
GenerateShared
(
ecies
.
ImportECDSAPublic
(
remoteRandomPubKey
),
skLen
,
skLen
)
if
err
!=
nil
{
return
}
// shared-secret = crypto.Sha3(ecdhe-shared-secret || crypto.Sha3(nonce || initiator-nonce))
var
sharedSecret
[]
byte
=
crypto
.
Sha3
(
append
(
dhSharedSecret
,
crypto
.
Sha3
(
append
(
nonce
,
remoteNonce
...
))
...
))
// token = crypto.Sha3(shared-secret)
sessionToken
=
crypto
.
Sha3
(
sharedSecret
)
// aes-secret = crypto.Sha3(ecdhe-shared-secret || shared-secret)
var
aesSecret
=
crypto
.
Sha3
(
append
(
dhSharedSecret
,
sharedSecret
...
))
// # destroy shared-secret
// mac-secret = crypto.Sha3(ecdhe-shared-secret || aes-secret)
var
macSecret
=
crypto
.
Sha3
(
append
(
dhSharedSecret
,
aesSecret
...
))
// # destroy ecdhe-shared-secret
// egress-mac = crypto.Sha3(mac-secret^nonce || auth)
var
egressMac
=
crypto
.
Sha3
(
append
(
Xor
(
macSecret
,
nonce
),
auth
...
))
// # destroy nonce
// ingress-mac = crypto.Sha3(mac-secret^initiator-nonce || auth),
var
ingressMac
=
crypto
.
Sha3
(
append
(
Xor
(
macSecret
,
remoteNonce
),
auth
...
))
// # destroy remote-nonce
rw
=
&
secretRW
{
aesSecret
:
aesSecret
,
macSecret
:
macSecret
,
egressMac
:
egressMac
,
ingressMac
:
ingressMac
,
}
return
}
func
Xor
(
one
,
other
[]
byte
)
(
xor
[]
byte
)
{
for
i
:=
0
;
i
<
len
(
one
);
i
++
{
xor
[
i
]
=
one
[
i
]
^
other
[
i
]
}
return
}
This diff is collapsed.
Click to expand it.
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