func eciesEncrypt(rand io.Reader, pub *ecdsa.PublicKey, s1, s2 []byte, plain []byte) ([]byte, error) { params := pub.Curve // Select an ephemeral elliptic curve key pair associated with // elliptic curve domain parameters params priv, Rx, Ry, err := elliptic.GenerateKey(pub.Curve, rand) //fmt.Printf("Rx %s\n", utils.EncodeBase64(Rx.Bytes())) //fmt.Printf("Ry %s\n", utils.EncodeBase64(Ry.Bytes())) // Convert R=(Rx,Ry) to an octed string R bar // This is uncompressed Rb := elliptic.Marshal(pub.Curve, Rx, Ry) // Derive a shared secret field element z from the ephemeral secret key k // and convert z to an octet string Z z, _ := params.ScalarMult(pub.X, pub.Y, priv) Z := z.Bytes() //fmt.Printf("Z %s\n", utils.EncodeBase64(Z)) // generate keying data K of length ecnKeyLen + macKeyLen octects from Z // ans s1 kE := make([]byte, 32) kM := make([]byte, 32) hkdf := hkdf.New(primitives.GetDefaultHash(), Z, s1, nil) _, err = hkdf.Read(kE) if err != nil { return nil, err } _, err = hkdf.Read(kM) if err != nil { return nil, err } // Use the encryption operation of the symmetric encryption scheme // to encrypt m under EK as ciphertext EM EM, err := aesEncrypt(kE, plain) // Use the tagging operation of the MAC scheme to compute // the tag D on EM || s2 mac := hmac.New(primitives.GetDefaultHash(), kM) mac.Write(EM) if len(s2) > 0 { mac.Write(s2) } D := mac.Sum(nil) // Output R,EM,D ciphertext := make([]byte, len(Rb)+len(EM)+len(D)) //fmt.Printf("Rb %s\n", utils.EncodeBase64(Rb)) //fmt.Printf("EM %s\n", utils.EncodeBase64(EM)) //fmt.Printf("D %s\n", utils.EncodeBase64(D)) copy(ciphertext, Rb) copy(ciphertext[len(Rb):], EM) copy(ciphertext[len(Rb)+len(EM):], D) return ciphertext, nil }
func eciesDecrypt(priv *ecdsa.PrivateKey, s1, s2 []byte, ciphertext []byte) ([]byte, error) { params := priv.Curve var ( rLen int hLen = primitives.GetDefaultHash()().Size() mStart int mEnd int ) //fmt.Printf("Decrypt\n") switch ciphertext[0] { case 2, 3: rLen = ((priv.PublicKey.Curve.Params().BitSize + 7) / 8) + 1 if len(ciphertext) < (rLen + hLen + 1) { return nil, fmt.Errorf("Invalid ciphertext len [First byte = %d]", ciphertext[0]) } break case 4: rLen = 2*((priv.PublicKey.Curve.Params().BitSize+7)/8) + 1 if len(ciphertext) < (rLen + hLen + 1) { return nil, fmt.Errorf("Invalid ciphertext len [First byte = %d]", ciphertext[0]) } break default: return nil, fmt.Errorf("Invalid ciphertext. Invalid first byte. [%d]", ciphertext[0]) } mStart = rLen mEnd = len(ciphertext) - hLen //fmt.Printf("Rb %s\n", utils.EncodeBase64(ciphertext[:rLen])) Rx, Ry := elliptic.Unmarshal(priv.Curve, ciphertext[:rLen]) if Rx == nil { return nil, errors.New("Invalid ephemeral PK") } if !priv.Curve.IsOnCurve(Rx, Ry) { return nil, errors.New("Invalid point on curve") } //fmt.Printf("Rx %s\n", utils.EncodeBase64(Rx.Bytes())) //fmt.Printf("Ry %s\n", utils.EncodeBase64(Ry.Bytes())) // Derive a shared secret field element z from the ephemeral secret key k // and convert z to an octet string Z z, _ := params.ScalarMult(Rx, Ry, priv.D.Bytes()) Z := z.Bytes() //fmt.Printf("Z %s\n", utils.EncodeBase64(Z)) // generate keying data K of length ecnKeyLen + macKeyLen octects from Z // ans s1 kE := make([]byte, 32) kM := make([]byte, 32) hkdf := hkdf.New(primitives.GetDefaultHash(), Z, s1, nil) _, err := hkdf.Read(kE) if err != nil { return nil, err } _, err = hkdf.Read(kM) if err != nil { return nil, err } // Use the tagging operation of the MAC scheme to compute // the tag D on EM || s2 and then compare mac := hmac.New(primitives.GetDefaultHash(), kM) mac.Write(ciphertext[mStart:mEnd]) if len(s2) > 0 { mac.Write(s2) } D := mac.Sum(nil) //fmt.Printf("EM %s\n", utils.EncodeBase64(ciphertext[mStart:mEnd])) //fmt.Printf("D' %s\n", utils.EncodeBase64(D)) //fmt.Printf("D %s\n", utils.EncodeBase64(ciphertext[mEnd:])) if subtle.ConstantTimeCompare(ciphertext[mEnd:], D) != 1 { return nil, errors.New("Tag check failed") } // Use the decryption operation of the symmetric encryption scheme // to decryptr EM under EK as plaintext plaintext, err := aesDecrypt(kE, ciphertext[mStart:mEnd]) return plaintext, err }