blob: 9419f892492f54f3741931f20f0e29fbacf54844 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package crypto
/*
#cgo CFLAGS: -O2
#cgo LDFLAGS: -lamcl_curve_SECP256K1 -lamcl_core
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <amcl/amcl.h>
#include <amcl/randapi.h>
#include <amcl/ecdh_SECP256K1.h>
*/
import "C"
import (
"crypto/rand"
"encoding/hex"
"github.com/pkg/errors"
)
const (
hashFunc = C.int(C.SHA256)
)
var (
paramP1 = CreateOctet([]byte{0, 1, 2})
paramP2 = CreateOctet([]byte{0, 1, 2, 3})
)
// Secp256k1Encrypt encrypts a message using ECP_SECP256K1_ECIES
func Secp256k1Encrypt(message, publicKey string) (C, V, T string, err error) {
dec := &hexBatchDecoder{}
wOctet := dec.decodeOctet(publicKey)
if dec.err != nil {
err = dec.err
return
}
seed := make([]byte, 32)
rand.Read(seed)
rng := NewRand(seed)
mOctet := CreateOctet([]byte(message))
//Results
vPtr := NewOctet(65)
hmacPtr := NewOctet(32)
cypherPtr := NewOctet(len(message) + 16 - (len(message) % 16))
C.ECP_SECP256K1_ECIES_ENCRYPT(hashFunc, paramP1, paramP2, (*C.csprng)(rng), (*C.octet)(wOctet), (*C.octet)(mOctet), C.int(12), vPtr, cypherPtr, hmacPtr)
return hex.EncodeToString(cypherPtr.ToBytes()), hex.EncodeToString(vPtr.ToBytes()), hex.EncodeToString(hmacPtr.ToBytes()), nil
}
// Secp256k1Decrypt decrypts an encrypoted message using ECP_SECP256K1_ECIES
func Secp256k1Decrypt(C, V, T, sK string) (message string, err error) {
dec := &hexBatchDecoder{}
cOct := dec.decodeOctet(C)
vOct := dec.decodeOctet(V)
tOct := dec.decodeOctet(T)
uOct := dec.decodeOctet(sK)
if dec.err != nil {
err = dec.err
return
}
//Cast the cypherText back to Octets
mOct := NewOctet(len(C) + 16 - (len(C) % 16))
if C.ECP_SECP256K1_ECIES_DECRYPT(hashFunc, paramP1, paramP2, vOct, cOct, tOct, uOct, mOct) != 1 {
return "", errors.New("Cannot decrypt cyphertext")
}
b := mOct.ToBytes()
return string(b), nil
}
type hexBatchDecoder struct {
err error
}
func (d *hexBatchDecoder) decodeOctet(s string) *Octet {
if d.err != nil {
return nil
}
b, err := hex.DecodeString(s)
if err != nil {
d.err = err
return nil
}
return CreateOctet(b)
}