mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
Add new modexp package
This commit is contained in:
parent
d72ec587a7
commit
e131482fe2
8 changed files with 507 additions and 0 deletions
45
crypto/modexp/bigint/bigint.go
Normal file
45
crypto/modexp/bigint/bigint.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2024 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 bigint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModExp performs modular exponentiation using Go's big.Int
|
||||||
|
// result = base^exp mod mod
|
||||||
|
func ModExp(base, exp, mod []byte) ([]byte, error) {
|
||||||
|
baseBig := new(big.Int).SetBytes(base)
|
||||||
|
expBig := new(big.Int).SetBytes(exp)
|
||||||
|
modBig := new(big.Int).SetBytes(mod)
|
||||||
|
|
||||||
|
// Handle special cases
|
||||||
|
if modBig.BitLen() == 0 {
|
||||||
|
// Modulo 0 is undefined, return empty bytes
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if baseBig.BitLen() == 1 {
|
||||||
|
// If base == 1, then we can just return base % mod
|
||||||
|
result := baseBig.Mod(baseBig, modBig)
|
||||||
|
return result.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform modular exponentiation
|
||||||
|
result := new(big.Int).Exp(baseBig, expBig, modBig)
|
||||||
|
return result.Bytes(), nil
|
||||||
|
}
|
||||||
86
crypto/modexp/bigint/bigint_test.go
Normal file
86
crypto/modexp/bigint/bigint_test.go
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright 2024 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 bigint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestModExp(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
base string
|
||||||
|
exp string
|
||||||
|
mod string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple",
|
||||||
|
base: "2",
|
||||||
|
exp: "10",
|
||||||
|
mod: "1000",
|
||||||
|
want: "24",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "zero_exponent",
|
||||||
|
base: "12345",
|
||||||
|
exp: "0",
|
||||||
|
mod: "67890",
|
||||||
|
want: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "base_one",
|
||||||
|
base: "1",
|
||||||
|
exp: "999999",
|
||||||
|
mod: "1000",
|
||||||
|
want: "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "zero_modulus",
|
||||||
|
base: "2",
|
||||||
|
exp: "10",
|
||||||
|
mod: "0",
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
baseBig := new(big.Int)
|
||||||
|
baseBig.SetString(tt.base, 10)
|
||||||
|
expBig := new(big.Int)
|
||||||
|
expBig.SetString(tt.exp, 10)
|
||||||
|
modBig := new(big.Int)
|
||||||
|
modBig.SetString(tt.mod, 10)
|
||||||
|
wantBig := new(big.Int)
|
||||||
|
if tt.want != "" {
|
||||||
|
wantBig.SetString(tt.want, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := ModExp(baseBig.Bytes(), expBig.Bytes(), modBig.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ModExp error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(result, wantBig.Bytes()) {
|
||||||
|
t.Errorf("ModExp result mismatch: got %x, want %x", result, wantBig.Bytes())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
46
crypto/modexp/gmp/README.md
Normal file
46
crypto/modexp/gmp/README.md
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# GMP Wrapper for go-ethereum
|
||||||
|
|
||||||
|
A CGO wrapper for GMP's modular exponentiation functionality.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
You need to have GMP development libraries installed on your system:
|
||||||
|
|
||||||
|
- **Ubuntu/Debian**: `sudo apt-get install libgmp-dev`
|
||||||
|
- **Fedora/RHEL**: `sudo dnf install gmp-devel`
|
||||||
|
- **macOS**: `brew install gmp`
|
||||||
|
- **Windows**: See [GMP Windows builds](https://gmplib.org/)
|
||||||
|
|
||||||
|
> TODO: There is an alternative branch, where we compile from source however this is slightly messier (though it allows us to pin to a specific commit like we do for libsecp256k1)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This package provides a GMP-backed implementation for modular exponentiation using a direct C call to avoid multiple calls to cgo. The main usage is for the modexp precompile.
|
||||||
|
|
||||||
|
### Byte Array Interface
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/ethereum/go-ethereum/crypto/modexp/gmp"
|
||||||
|
|
||||||
|
base := []byte{0x02} // 2
|
||||||
|
exp := []byte{0x0A} // 10
|
||||||
|
mod := []byte{0x03, 0xE8} // 1000
|
||||||
|
|
||||||
|
result, err := gmp.ModExp(base, exp, mod)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// result = 24 (2^10 mod 1000)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run tests from the go-ethereum root directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test ./crypto/modexp/gmp/...
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
TODO -- whatever go-ethereum does.
|
||||||
96
crypto/modexp/gmp/gmp.go
Normal file
96
crypto/modexp/gmp/gmp.go
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright 2024 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 gmp
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lgmp
|
||||||
|
// #include "modexp.h"
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModExp performs modular exponentiation using GMP
|
||||||
|
// This is thread safe.
|
||||||
|
func ModExp(base, exp, mod []byte) ([]byte, error) {
|
||||||
|
// Handle empty modulus - return empty result (EVM behavior)
|
||||||
|
if len(mod) == 0 {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case: zero modulus
|
||||||
|
allZero := true
|
||||||
|
for _, b := range mod {
|
||||||
|
if b != 0 {
|
||||||
|
allZero = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if allZero {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate result buffer (size of modulus is the max possible result)
|
||||||
|
result := make([]byte, len(mod))
|
||||||
|
resultLen := C.size_t(len(result))
|
||||||
|
|
||||||
|
// Handle empty slices - pass a dummy non-nil pointer with length 0
|
||||||
|
// This avoids UB when the length is zero.
|
||||||
|
dummy := C.uint8_t(0)
|
||||||
|
var basePtr, expPtr, modPtr *C.uint8_t = &dummy, &dummy, &dummy
|
||||||
|
|
||||||
|
if len(base) > 0 {
|
||||||
|
basePtr = (*C.uint8_t)(unsafe.Pointer(&base[0]))
|
||||||
|
}
|
||||||
|
if len(exp) > 0 {
|
||||||
|
expPtr = (*C.uint8_t)(unsafe.Pointer(&exp[0]))
|
||||||
|
}
|
||||||
|
if len(mod) > 0 {
|
||||||
|
modPtr = (*C.uint8_t)(unsafe.Pointer(&mod[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call C function
|
||||||
|
ret := C.modexp_bytes(
|
||||||
|
basePtr, C.size_t(len(base)),
|
||||||
|
expPtr, C.size_t(len(exp)),
|
||||||
|
modPtr, C.size_t(len(mod)),
|
||||||
|
(*C.uint8_t)(unsafe.Pointer(&result[0])), &resultLen,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Keep the slices alive until after the C call completes
|
||||||
|
runtime.KeepAlive(base)
|
||||||
|
runtime.KeepAlive(exp)
|
||||||
|
runtime.KeepAlive(mod)
|
||||||
|
runtime.KeepAlive(result)
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
switch ret {
|
||||||
|
case 0:
|
||||||
|
// Success - trim result to actual size
|
||||||
|
if resultLen == 0 {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
return result[:resultLen], nil
|
||||||
|
case -1:
|
||||||
|
return nil, errors.New("invalid parameter")
|
||||||
|
case -2:
|
||||||
|
return nil, errors.New("result buffer too small")
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unknown error")
|
||||||
|
}
|
||||||
|
}
|
||||||
135
crypto/modexp/gmp/gmp_test.go
Normal file
135
crypto/modexp/gmp/gmp_test.go
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
// Copyright 2024 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 gmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestWrapperVsBigInt compares the wrapper with Go's math/big
|
||||||
|
func TestWrapperVsBigInt(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
base string
|
||||||
|
exp string
|
||||||
|
mod string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "small_numbers",
|
||||||
|
base: "2",
|
||||||
|
exp: "10",
|
||||||
|
mod: "1000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "medium_numbers",
|
||||||
|
base: "123456789",
|
||||||
|
exp: "987654321",
|
||||||
|
mod: "1000000007",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "large_numbers",
|
||||||
|
base: "123456789012345678901234567890",
|
||||||
|
exp: "987654321098765432109876543210",
|
||||||
|
mod: "111111111111111111111111111111",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "zero_exponent",
|
||||||
|
base: "12345",
|
||||||
|
exp: "0",
|
||||||
|
mod: "67890",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Parse numbers
|
||||||
|
baseBig := new(big.Int)
|
||||||
|
baseBig.SetString(tt.base, 10)
|
||||||
|
expBig := new(big.Int)
|
||||||
|
expBig.SetString(tt.exp, 10)
|
||||||
|
modBig := new(big.Int)
|
||||||
|
modBig.SetString(tt.mod, 10)
|
||||||
|
|
||||||
|
// Test with wrapper
|
||||||
|
baseBytes := baseBig.Bytes()
|
||||||
|
expBytes := expBig.Bytes()
|
||||||
|
modBytes := modBig.Bytes()
|
||||||
|
|
||||||
|
wrapperResult, err := ModExp(baseBytes, expBytes, modBytes)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Wrapper error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with math/big
|
||||||
|
bigResult := new(big.Int)
|
||||||
|
bigResult.Exp(baseBig, expBig, modBig)
|
||||||
|
|
||||||
|
expectedResult := bigResult.Bytes()
|
||||||
|
|
||||||
|
// Compare results
|
||||||
|
if !bytes.Equal(wrapperResult, expectedResult) {
|
||||||
|
t.Errorf("Results differ:\nWrapper: %x\nExpected: %x",
|
||||||
|
wrapperResult, expectedResult)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkWrapperVsExisting compares performance
|
||||||
|
func BenchmarkModExp(b *testing.B) {
|
||||||
|
base := make([]byte, 60)
|
||||||
|
exp := make([]byte, 60)
|
||||||
|
mod := make([]byte, 60)
|
||||||
|
|
||||||
|
for i := range base {
|
||||||
|
base[i] = byte(i * 17)
|
||||||
|
exp[i] = byte(i * 31)
|
||||||
|
mod[i] = byte(255 - i)
|
||||||
|
}
|
||||||
|
mod[59] |= 0x01
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _ = ModExp(base, exp, mod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkModExpBigInt(b *testing.B) {
|
||||||
|
baseBytes := make([]byte, 60)
|
||||||
|
expBytes := make([]byte, 60)
|
||||||
|
modBytes := make([]byte, 60)
|
||||||
|
|
||||||
|
for i := range baseBytes {
|
||||||
|
baseBytes[i] = byte(i * 17)
|
||||||
|
expBytes[i] = byte(i * 31)
|
||||||
|
modBytes[i] = byte(255 - i)
|
||||||
|
}
|
||||||
|
modBytes[59] |= 0x01
|
||||||
|
|
||||||
|
base := new(big.Int).SetBytes(baseBytes)
|
||||||
|
exp := new(big.Int).SetBytes(expBytes)
|
||||||
|
mod := new(big.Int).SetBytes(modBytes)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
result := new(big.Int)
|
||||||
|
result.Exp(base, exp, mod)
|
||||||
|
_ = result.Bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
55
crypto/modexp/gmp/modexp.c
Normal file
55
crypto/modexp/gmp/modexp.c
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include <gmp.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int modexp_bytes(
|
||||||
|
const uint8_t* base, size_t base_len,
|
||||||
|
const uint8_t* exp, size_t exp_len,
|
||||||
|
const uint8_t* mod, size_t mod_len,
|
||||||
|
uint8_t* result, size_t* result_len)
|
||||||
|
{
|
||||||
|
mpz_t base_mpz, exp_mpz, mod_mpz, result_mpz;
|
||||||
|
|
||||||
|
// Check for NULL pointers
|
||||||
|
if (!base || !exp || !mod || !result || !result_len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize GMP integers
|
||||||
|
mpz_inits(base_mpz, exp_mpz, mod_mpz, result_mpz, NULL);
|
||||||
|
|
||||||
|
// Import big-endian byte arrays into GMP integers
|
||||||
|
// Handle empty arrays specially - GMP treats NULL with size 0 as 0
|
||||||
|
if (base_len > 0) {
|
||||||
|
mpz_import(base_mpz, base_len, 1, 1, 0, 0, base);
|
||||||
|
}
|
||||||
|
if (exp_len > 0) {
|
||||||
|
mpz_import(exp_mpz, exp_len, 1, 1, 0, 0, exp);
|
||||||
|
}
|
||||||
|
if (mod_len > 0) {
|
||||||
|
mpz_import(mod_mpz, mod_len, 1, 1, 0, 0, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform modular exponentiation
|
||||||
|
mpz_powm(result_mpz, base_mpz, exp_mpz, mod_mpz);
|
||||||
|
|
||||||
|
// Get exact size needed for result
|
||||||
|
size_t needed = 0;
|
||||||
|
mpz_export(NULL, &needed, 1, 1, 0, 0, result_mpz);
|
||||||
|
|
||||||
|
// Check if result buffer is large enough
|
||||||
|
if (*result_len < needed) {
|
||||||
|
mpz_clears(base_mpz, exp_mpz, mod_mpz, result_mpz, NULL);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export result to big-endian byte array
|
||||||
|
mpz_export(result, &needed, 1, 1, 0, 0, result_mpz);
|
||||||
|
*result_len = needed;
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
mpz_clears(base_mpz, exp_mpz, mod_mpz, result_mpz, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
15
crypto/modexp/gmp/modexp.h
Normal file
15
crypto/modexp/gmp/modexp.h
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef MODEXP_H
|
||||||
|
#define MODEXP_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// Perform modular exponentiation: base^exp mod mod
|
||||||
|
// Returns 0 on success, -1 on invalid input, -2 if result buffer too small
|
||||||
|
int modexp_bytes(
|
||||||
|
const uint8_t* base, size_t base_len,
|
||||||
|
const uint8_t* exp, size_t exp_len,
|
||||||
|
const uint8_t* mod, size_t mod_len,
|
||||||
|
uint8_t* result, size_t* result_len);
|
||||||
|
|
||||||
|
#endif // MODEXP_H
|
||||||
29
crypto/modexp/modexp.go
Normal file
29
crypto/modexp/modexp.go
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2024 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 modexp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/modexp/gmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModExp performs modular exponentiation on byte arrays
|
||||||
|
// result = base^exp mod mod
|
||||||
|
// This uses the gmp implementation by default.
|
||||||
|
// To use bigint implementation, import crypto/modexp/bigint directly.
|
||||||
|
func ModExp(base, exp, mod []byte) ([]byte, error) {
|
||||||
|
return gmp.ModExp(base, exp, mod)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue