Reputation:
for result, i want to calculate a value X as apiKey with formula this
Pubkey1 = Privkey1 * G
Pubkey2 = Privkey2 * G
then we get
Privkey2 * Pubkey1 = Privkey1 * Pubkey2
also equal
Privkey2 * Privkey1 * G = Privkey1 * Privkey2 * G = X
then service and client can use X as key for signature。
i am new one in golang and ED25519 or ECDSA,if i was wrong,hope someone can figure out, thanks a lot!
the lib which i used is crypto/ed25519
in this lib, i found a func GeDoubleScalarMultVartime(), it can calculate with formula
r = a*A + b*B
i have no idea how to calculate X, so i consider if i set b = 0,
r = a*A + 0*B = a*A
and then i write some code to do a verification。
in lib crypto/ed25519, all kernel func located in folder internal,so i write some func to expose to me
// get ProjectiveGroupElement struct
func GetProjectiveGroupElement() edwards25519.ProjectiveGroupElement {
var R edwards25519.ProjectiveGroupElement
return R
}
// get GeDoubleScalarMultVartime function
func GeDoubleScalar(r *edwards25519.ProjectiveGroupElement, a * [32]byte, A *edwards25519.ExtendedGroupElement, b *[32]byte) {
edwards25519.GeDoubleScalarMultVartime(r, a, A, b)
}
// return PublicKey correspondence ExtendedGroupElement immediate, which used in GeDoubleScalarMultVartime() as param A instead PublicKey
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, edwards25519.ExtendedGroupElement, error) {
if rand == nil {
rand = cryptorand.Reader
}
seed := make([]byte, SeedSize)
if _, err := io.ReadFull(rand, seed); err != nil {
var B edwards25519.ExtendedGroupElement
return nil, nil, B, err
}
privateKey, A := NewKeyFromSeed(seed)
publicKey := make([]byte, PublicKeySize)
copy(publicKey, privateKey[32:])
return publicKey, privateKey, A, nil
}
func NewKeyFromSeed(seed []byte) (PrivateKey, edwards25519.ExtendedGroupElement){
if l := len(seed); l != SeedSize {
panic("ed25519: bad seed length: " + strconv.Itoa(l))
}
digest := sha512.Sum512(seed)
digest[0] &= 248
digest[31] &= 127
digest[31] |= 64
var A edwards25519.ExtendedGroupElement
var hBytes [32]byte
copy(hBytes[:], digest[:])
edwards25519.GeScalarMultBase(&A, &hBytes)
var publicKeyBytes [32]byte
A.ToBytes(&publicKeyBytes)
privateKey := make([]byte, PrivateKeySize)
copy(privateKey, seed)
copy(privateKey[32:], publicKeyBytes[:])
return privateKey, A
}
this is test code
package main
import (
"crypto/rand"
"golang.org/x/crypto/ed25519"
)
func main() {
pubK, privK, localA, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Printf("error")
}
var R = ed25519.GetProjectiveGroupElement()
var testpubKey [32]byte
var testprivKey [32]byte
for i,v := range pubK {
testpubKey[i] = v
}
for i,v := range privK {
if i < 32 {
testprivKey[i] = v
}
}
var apikey1 [32]byte
var b [32]byte //set b = 0
log.Printf("localA:%x\n", localA)
pubK2, privK2, localB, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Printf("error")
}
var R2 = ed25519.GetProjectiveGroupElement()
var testpubKey2 [32]byte
var testprivKey2 [32]byte
for i,v := range pubK2 {
testpubKey2[i] = v
}
for i,v := range privK2 {
if i < 32 {
testprivKey2[i] = v
}
}
var apikey2 [32]byte
var b2 [32]byte //set b = 0
log.Printf("localB:%x\n", localB)
ed25519.GeDoubleScalar(&R2, &testprivKey2, &localA, &b2)
R2.ToBytes(&apikey2)
log.Printf("apikey2:%x\n", apikey2)
log.Printf("privK2:%x\n", privK2)
ed25519.GeDoubleScalar(&R, &testprivKey, &localB, &b)
R.ToBytes(&apikey1)
log.Printf("apikey:%x\n", apikey1)
log.Printf("privK1:%x\n", privK)
}
the result
2018/08/28 11:17:23 apikey2:c025975d177059792498509fc4d4a8586b0039273d80c62760cf52064d2555bb
2018/08/28 11:17:23 privK2:ebd70f9b2254bee1de3a105e274fc6b0d65da8d66b1ba47d760a47a3f8b5fe866bc1d3fa1db801b49dc5521cf0b440c84894dd03e2871581c2a84cdc9c92e037
2018/08/28 11:17:23 apikey:0cfd0e75e8ec990d93d2768b101c70c0bf42e38e869afacfcbc1e61183fdd03d
2018/08/28 11:17:23 privK1:5eee36a68309f49fb73e1a93338c3a9173ce37cf5b2c0d27d344b45a7f441c37cd021701c36a5322eacbba6e4a49eda2fbfa32bfe5baf859d9851ecff714721a
the two apikey are different, am i used lib in a wrong way? or i have a wrong cognition with ed25519? wish someone can give me help. thanks
my english is not so good, if you get confused with my discription,just figure it out, thanks again
Upvotes: 1
Views: 1466
Reputation: 401
Out of the blue, I'd say it is probably because you are using GenerateKey
which calls NewKeyFromSeed
where the privateKey is actually copied from the seed copy(privateKey, seed)
, and so you are using the seed instead of the digest
actually used in NewKeyFromSeed
, but in order to do the scalar trick you want to do, you have to use the actual private scalar in your computation, with the lower and upper bits sets as they should.
Instead modify your NewKeyFromSeed
to do:
copy(privateKey, digest)
and maybe it will work as intended.
Disclaimer: I have only compiled this code in my head, so I might be off. If you want more help, you should post a MWE, and maybe head to StackOverflow, since it is more like a debugging code question than a crypto question.
Upvotes: 1