├── .github └── workflows │ ├── main.yml │ └── release.yml ├── .gitignore ├── .gitmodules ├── Makefile ├── bls ├── bls.go ├── bls_test.go ├── callback.go ├── cast.go ├── dfinity_test.go ├── include │ ├── bls │ │ ├── bls.h │ │ └── bls384_256.h │ └── mcl │ │ ├── bn.h │ │ ├── bn_c384_256.h │ │ └── curve_type.h ├── link.go ├── link_ios.go ├── link_iossimulator.go └── mcl.go ├── examples ├── agg-verify.go └── cast-sample.go ├── go.mod ├── obj └── .emptydir ├── patch ├── bls.patch └── mcl.patch ├── readme.md └── setup_vendor.sh /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: [push] 3 | 4 | jobs: 5 | Run-on-ubuntu: 6 | name: Run on ubuntu 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - run: | 11 | git submodule update --init --recursive 12 | sudo apt install nasm 13 | make clean 14 | make CXX=clang++ 15 | go test -v ./bls 16 | 17 | Run-on-Intel-macos: 18 | name: Run on Intel macos 19 | runs-on: macos-13 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: actions/setup-go@v5 23 | with: 24 | go-version: '1.18.x' 25 | - run: | 26 | git submodule update --init --recursive 27 | brew install nasm 28 | make clean 29 | make 30 | go test -v ./bls 31 | 32 | Run-on-ARM-macos: 33 | name: Run on macos 34 | # Intel Mac 35 | runs-on: macos-latest 36 | steps: 37 | - uses: actions/checkout@v4 38 | - uses: actions/setup-go@v5 39 | with: 40 | go-version: '1.18.x' 41 | - run: | 42 | git submodule update --init --recursive 43 | make clean 44 | make 45 | go test -v ./bls 46 | 47 | Run-on-windows: 48 | name: Run on windows 49 | runs-on: windows-latest 50 | steps: 51 | - uses: msys2/setup-msys2@v2 52 | with: 53 | msystem: MINGW64 54 | #msystem: UCRT64 55 | update: true 56 | platform-check-severity: warn 57 | install: >- 58 | make 59 | python3 60 | mingw-w64-x86_64-gcc 61 | mingw-w64-x86_64-go 62 | - uses: msys2/setup-msys2@v2 63 | # - uses: actions/checkout@v4 64 | - run: | 65 | git clone -b release https://github.com/herumi/bls-go-binary 66 | cd bls-go-binary 67 | #git submodule update --init --recursive 68 | #make MCL_STATIC_CODE=0 69 | go test -v ./bls 70 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | 4 | permissions: 5 | contents: write 6 | repository-projects: write 7 | 8 | concurrency: 9 | group: "release-${{ github.ref }}" 10 | cancel-in-progress: true 11 | 12 | on: 13 | workflow_dispatch: 14 | inputs: 15 | version: 16 | description: 'release/tag: vX.Y.Z' 17 | required: true 18 | 19 | 20 | jobs: 21 | create-branch: 22 | runs-on: ubuntu-latest 23 | 24 | steps: 25 | - name: Checkout code 26 | uses: actions/checkout@v4 27 | 28 | - name: Create branch 29 | env: 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 31 | run: | 32 | git pull 33 | git checkout release 2>/dev/null || git checkout -b release 34 | rm -rf ./src/bls && mkdir -p ./src/bls 35 | git merge origin/master -q -m "chore(git): merged latest master" 36 | git submodule update --init --recursive 37 | 38 | git config user.name github-actions 39 | git config user.email github-actions@github.com 40 | git push --set-upstream origin release 41 | build-linux: 42 | # For Linux build we use an Ubuntu version that's as old as possible so that 43 | # the generated artifacts are compatible with not-so-recent systems 44 | runs-on: ubuntu-20.04 45 | needs: create-branch 46 | steps: 47 | - name: Checkout code 48 | uses: actions/checkout@v4 49 | 50 | - name: Setup Go 51 | uses: actions/setup-go@v5 52 | with: 53 | go-version: ^1.20 54 | 55 | - name: Install Java 56 | uses: actions/setup-java@v4 57 | with: 58 | distribution: 'temurin' 59 | java-version: '11' 60 | 61 | - uses: android-actions/setup-android@v2 62 | 63 | - name: Install Android Platform 64 | run: | 65 | sdkmanager "platform-tools" 66 | sdkmanager "platforms;android-29" 67 | sdkmanager "build-tools;29.0.2" 68 | 69 | - uses: nttld/setup-ndk@v1 70 | id: setup-ndk 71 | with: 72 | ndk-version: r21d 73 | 74 | - name: Build linux 75 | env: 76 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 77 | run: | 78 | git pull && git checkout release 79 | git submodule update --init --recursive 80 | 81 | sudo apt update 82 | sudo apt install nasm 83 | 84 | [ -d ./bls/lib/linux/ ] && rm -rf ./bls/lib/linux/ 85 | make clean 86 | 87 | mkdir -p ./bls/lib/linux/ 88 | 89 | #make CXX=clang++ # avoid crashes on non-AVX CPUs 90 | make 91 | make clean 92 | # build linux/arm64 93 | sudo apt-get install gcc-multilib 94 | make aarch64 95 | 96 | git config user.name github-actions 97 | git config user.email github-actions@github.com 98 | 99 | git add ./bls/lib/linux -f 100 | 101 | changes=$(git diff --staged --numstat | wc -l) 102 | if [[ $changes -gt 0 ]] 103 | then 104 | git commit -m "fix(release): added libs for linux(amd64/arm64)" 105 | git push 106 | fi 107 | 108 | - name: Build android 109 | env: 110 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 111 | run: | 112 | git pull && git checkout release 113 | 114 | [ -d ./bls/lib/android/ ] && rm -rf ./bls/lib/android/ 115 | make clean 116 | 117 | mkdir -p ./bls/lib/android/ 118 | 119 | make android 120 | 121 | git config user.name github-actions 122 | git config user.email github-actions@github.com 123 | 124 | git add ./bls/lib/android/ -f 125 | 126 | changes=$(git diff --staged --numstat | wc -l) 127 | if [[ $changes -gt 0 ]] 128 | then 129 | git commit -m "fix(release): added libs for android" 130 | git push 131 | fi 132 | build-macos: 133 | runs-on: macos-13 # macos-14 causes link error 134 | needs: build-linux 135 | steps: 136 | - name: Checkout code 137 | uses: actions/checkout@v4 138 | 139 | - name: Setup Go 140 | uses: actions/setup-go@v5 141 | with: 142 | go-version: ^1.20 143 | 144 | - name: Build darwin 145 | env: 146 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 147 | run: | 148 | git pull && git checkout release 149 | git submodule update --init --recursive 150 | 151 | brew install nasm 152 | 153 | [ -d ./bls/lib/darwin/ ] && rm -rf ./bls/lib/darwin/ 154 | make clean 155 | 156 | mkdir -p ./bls/lib/darwin/ 157 | 158 | make ARCH=x86_64 159 | make clean 160 | make ARCH=arm64 161 | 162 | git config user.name github-actions 163 | git config user.email github-actions@github.com 164 | 165 | git add ./bls/lib/darwin/ -f 166 | 167 | changes=$(git diff --staged --numstat | wc -l) 168 | if [[ $changes -gt 0 ]] 169 | then 170 | git commit -m "fix(release): added libs for darwin" 171 | git push 172 | fi 173 | 174 | - name: Build ios 175 | env: 176 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 177 | run: | 178 | git pull && git checkout release 179 | git submodule update --init --recursive 180 | 181 | [ -d ./bls/lib/ios ] && rm -rf ./bls/lib/ios 182 | [ -d ./bls/lib/iossimulator ] && rm -rf ./bls/lib/iossimulator 183 | make clean 184 | 185 | mkdir -p ./bls/lib/ios 186 | mkdir -p ./bls/lib/iossimulator 187 | 188 | git config user.name github-actions 189 | git config user.email github-actions@github.com 190 | 191 | make ios 192 | make ios_simulator 193 | 194 | git add ./bls/lib/ios -f 195 | git add ./bls/lib/iossimulator -f 196 | 197 | changes=$(git diff --staged --numstat | wc -l) 198 | if [[ $changes -gt 0 ]] 199 | then 200 | git commit -m "fix(release): added libs for ios/ios simulator" 201 | git push 202 | fi 203 | 204 | build-windows: 205 | runs-on: windows-latest 206 | needs: build-macos 207 | steps: 208 | - name: Checkout code 209 | uses: actions/checkout@v4 210 | 211 | - name: Setup Go 212 | uses: actions/setup-go@v5 213 | with: 214 | go-version: ^1.20 215 | 216 | - name: Install MSYS2 217 | uses: msys2/setup-msys2@v2 218 | with: 219 | update: true 220 | msystem: MINGW64 221 | install: base-devel git gcc make python3 nasm # mingw-w64-x86_64-clang 222 | 223 | - name: Build windows 224 | # shell: msys2 {0} 225 | env: 226 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 227 | run: | 228 | git pull && git checkout release 229 | git submodule update --init --recursive 230 | 231 | gcc --version 232 | python3 --version 233 | 234 | git checkout . 235 | if (Test-Path "./bls/lib/windows/amd64") { 236 | Remove-Item "./bls/lib/windows/amd64" -Recurse -Force 237 | } 238 | make clean 239 | # make -j # ar gives an error for some reason, so use the followings: 240 | 241 | md "./bls/lib/windows/amd64" 242 | 243 | make -C ./src/bls -f Makefile.onelib LIB_DIR=./ 244 | cp ./src/bls/libbls384_256.a ./bls/lib/windows/amd64/libbls384_256.a 245 | 246 | git config user.name github-actions 247 | git config user.email github-actions@github.com 248 | git add ./bls/lib/windows -f && git commit -m "fix(release): added libs for windows" && git push 249 | 250 | 251 | create-release: 252 | runs-on: ubuntu-latest 253 | needs: build-windows 254 | steps: 255 | - name: Checkout code 256 | uses: actions/checkout@v4 257 | - name: Set hash 258 | id: set-hash 259 | env: 260 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 261 | run: | 262 | git pull && git checkout release 263 | git submodule update --init --recursive 264 | git branch -av 265 | git rev-parse HEAD 266 | echo "hash=$(git rev-parse HEAD)" >> "$GITHUB_ENV" 267 | 268 | - name: show 269 | run: | 270 | echo "hash" "${{ env.hash }}" 271 | 272 | - name: Create Release 273 | id: create_release 274 | run: gh release create "${{ github.event.inputs.version }}" -t "${{ github.event.inputs.version }}" --target "release" --latest 275 | env: 276 | GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 277 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ios 2 | iossimulator 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/bls"] 2 | path = src/bls 3 | url = https://github.com/herumi/bls 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | -include ETH.cfg 2 | ARCH?=$(shell uname -m) 3 | SRC_DIR?=src/ 4 | BLS_DIR?=$(SRC_DIR)/bls 5 | MCL_DIR?=$(BLS_DIR)/mcl 6 | all: 7 | $(MAKE) -f $(BLS_DIR)/Makefile.onelib BLS_DIR=$(BLS_DIR) MCL_DIR=$(MCL_DIR) OUT_DIR=$(shell pwd) ARCH=$(ARCH) ETH_CFLAGS=$(ETH_CFLAGS) all 8 | ios: 9 | $(MAKE) -f $(BLS_DIR)/Makefile.onelib BLS_DIR=$(BLS_DIR) MCL_DIR=$(MCL_DIR) OUT_DIR=$(shell pwd) ETH_CFLAGS=$(ETH_CFLAGS) ios 10 | ios_simulator: 11 | $(MAKE) -f $(BLS_DIR)/Makefile.onelib BLS_DIR=$(BLS_DIR) MCL_DIR=$(MCL_DIR) OUT_DIR=$(shell pwd) ETH_CFLAGS=$(ETH_CFLAGS) ios_simulator 12 | 13 | aarch64: # for cross compile on x64-linux 14 | $(MAKE) -f $(BLS_DIR)/Makefile.onelib BLS_DIR=$(BLS_DIR) MCL_DIR=$(MCL_DIR) OUT_DIR=$(shell pwd) ETH_CFLAGS=$(ETH_CFLAGS) build_aarch64 CXX=clang++ 15 | riscv64: # for cross compile on x64-linux 16 | $(MAKE) -f $(BLS_DIR)/Makefile.onelib BLS_DIR=$(BLS_DIR) MCL_DIR=$(MCL_DIR) OUT_DIR=$(shell pwd) ETH_CFLAGS=$(ETH_CFLAGS) build_riscv64 CXX=clang++ 17 | 18 | NDK_BUILD?=ndk-build 19 | android: 20 | $(MAKE) -f $(BLS_DIR)/Makefile.onelib BLS_DIR=$(BLS_DIR) MCL_DIR=$(MCL_DIR) OUT_DIR=$(shell pwd) ETH_CFLAGS=$(ETH_CFLAGS) NDK_BUILD=$(NDK_BUILD) BLS_LIB_SHARED=$(BLS_LIB_SHARED) android 21 | 22 | update: 23 | cp $(BLS_DIR)/include/bls/bls.h bls/include/bls/. 24 | cp $(BLS_DIR)/include/bls/bls384_256.h bls/include/bls/. 25 | cp $(MCL_DIR)/include/mcl/bn.h bls/include/mcl/. 26 | cp $(MCL_DIR)/include/mcl/bn_c384_256.h bls/include/mcl/. 27 | cp $(MCL_DIR)/include/mcl/curve_type.h bls/include/mcl/. 28 | patch -o - -p0 ../bls/ffi/go/bls/mcl.go bls/mcl.go 29 | patch -o - -p0 ../bls/ffi/go/bls/bls.go bls/bls.go 30 | 31 | update_patch: 32 | -diff -up $(BLS_DIR)/ffi/go/bls/mcl.go bls/mcl.go > patch/mcl.patch 33 | -diff -up $(BLS_DIR)/ffi/go/bls/bls.go bls/bls.go > patch/bls.patch 34 | 35 | clean: 36 | $(MAKE) -C $(MCL_DIR) clean 37 | $(MAKE) -C $(BLS_DIR) clean 38 | $(RM) -rf obj/*.o android/obj/* bls/lib/android/* 39 | 40 | .PHONY: android ios each_ios clean 41 | -------------------------------------------------------------------------------- /bls/bls.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | /* 4 | #cgo CFLAGS:-I${SRCDIR}./include 5 | typedef unsigned int (*ReadRandFunc)(void *, void *, unsigned int); 6 | int wrapReadRandCgo(void *self, void *buf, unsigned int n); 7 | #include 8 | #include 9 | */ 10 | import "C" 11 | import ( 12 | "encoding/hex" 13 | "encoding/json" 14 | "fmt" 15 | "io" 16 | "unsafe" 17 | ) 18 | 19 | const ethMode = false 20 | 21 | const EthModeOld = C.BLS_ETH_MODE_OLD 22 | const EthModeDraft05 = C.BLS_ETH_MODE_DRAFT_05 23 | const EthModeDraft06 = C.BLS_ETH_MODE_DRAFT_06 24 | const EthModeDraft07 = C.BLS_ETH_MODE_DRAFT_07 25 | const EthModeLatest = C.BLS_ETH_MODE_LATEST 26 | 27 | func hex2byte(s string) ([]byte, error) { 28 | if (len(s) & 1) == 1 { 29 | return nil, fmt.Errorf("odd length") 30 | } 31 | return hex.DecodeString(s) 32 | } 33 | 34 | // SetETHmode -- 35 | // Set hash function 36 | // mode = EthModeOld or EthModeLatest(=EthModeDraft07) 37 | // error if curve != MCL_BLS12_381 38 | func SetETHmode(mode int) error { 39 | if C.blsSetETHmode(C.int(mode)) != 0 { 40 | return fmt.Errorf("ERR SetETHmode") 41 | } 42 | return nil 43 | } 44 | 45 | // Init -- 46 | // call this function before calling all the other operations 47 | // this function is not thread safe 48 | func Init(curve int) error { 49 | err := C.blsInit(C.int(curve), C.MCLBN_COMPILED_TIME_VAR) 50 | if err != 0 { 51 | return fmt.Errorf("ERR Init curve=%d", curve) 52 | } 53 | if !ethMode { 54 | return nil 55 | } 56 | return SetETHmode(C.BLS_ETH_MODE_LATEST) 57 | } 58 | 59 | // ID -- 60 | type ID struct { 61 | v C.blsId 62 | } 63 | 64 | // Serialize -- 65 | func (id *ID) Serialize() []byte { 66 | buf := make([]byte, 2048) 67 | // #nosec 68 | n := C.blsIdSerialize(unsafe.Pointer(&buf[0]), C.mclSize(len(buf)), &id.v) 69 | if n == 0 { 70 | panic("err blsIdSerialize") 71 | } 72 | return buf[:n] 73 | } 74 | 75 | // Deserialize -- 76 | func (id *ID) Deserialize(buf []byte) error { 77 | // #nosec 78 | n := C.blsIdDeserialize(&id.v, getPointer(buf), C.mclSize(len(buf))) 79 | if n == 0 || int(n) != len(buf) { 80 | return fmt.Errorf("err blsIdDeserialize %x", buf) 81 | } 82 | return nil 83 | } 84 | 85 | // GetLittleEndian -- alias of Serialize 86 | func (id *ID) GetLittleEndian() []byte { 87 | return id.Serialize() 88 | } 89 | 90 | // SetLittleEndian -- 91 | func (id *ID) SetLittleEndian(buf []byte) error { 92 | // #nosec 93 | err := C.blsIdSetLittleEndian(&id.v, getPointer(buf), C.mclSize(len(buf))) 94 | if err != 0 { 95 | return fmt.Errorf("err blsIdSetLittleEndian %x", err) 96 | } 97 | return nil 98 | } 99 | 100 | // SerializeToHexStr -- 101 | func (id *ID) SerializeToHexStr() string { 102 | return hex.EncodeToString(id.Serialize()) 103 | } 104 | 105 | // DeserializeHexStr -- 106 | func (id *ID) DeserializeHexStr(s string) error { 107 | a, err := hex2byte(s) 108 | if err != nil { 109 | return err 110 | } 111 | return id.Deserialize(a) 112 | } 113 | 114 | // GetHexString -- 115 | func (id *ID) GetHexString() string { 116 | buf := make([]byte, 2048) 117 | // #nosec 118 | n := C.blsIdGetHexStr((*C.char)(unsafe.Pointer(&buf[0])), C.mclSize(len(buf)), &id.v) 119 | if n == 0 { 120 | panic("err blsIdGetHexStr") 121 | } 122 | return string(buf[:n]) 123 | } 124 | 125 | // GetDecString -- 126 | func (id *ID) GetDecString() string { 127 | buf := make([]byte, 2048) 128 | // #nosec 129 | n := C.blsIdGetDecStr((*C.char)(unsafe.Pointer(&buf[0])), C.mclSize(len(buf)), &id.v) 130 | if n == 0 { 131 | panic("err blsIdGetDecStr") 132 | } 133 | return string(buf[:n]) 134 | } 135 | 136 | // SetHexString -- 137 | func (id *ID) SetHexString(s string) error { 138 | buf := []byte(s) 139 | // #nosec 140 | err := C.blsIdSetHexStr(&id.v, (*C.char)(getPointer(buf)), C.mclSize(len(buf))) 141 | if err != 0 { 142 | return fmt.Errorf("err blsIdSetHexStr %s", s) 143 | } 144 | return nil 145 | } 146 | 147 | // SetDecString -- 148 | func (id *ID) SetDecString(s string) error { 149 | buf := []byte(s) 150 | // #nosec 151 | err := C.blsIdSetDecStr(&id.v, (*C.char)(getPointer(buf)), C.mclSize(len(buf))) 152 | if err != 0 { 153 | return fmt.Errorf("err blsIdSetDecStr %s", s) 154 | } 155 | return nil 156 | } 157 | 158 | // IsEqual -- 159 | func (id *ID) IsEqual(rhs *ID) bool { 160 | if id == nil || rhs == nil { 161 | return false 162 | } 163 | return C.blsIdIsEqual(&id.v, &rhs.v) == 1 164 | } 165 | 166 | // SecretKey -- 167 | type SecretKey struct { 168 | v C.blsSecretKey 169 | } 170 | 171 | // Serialize -- 172 | func (sec *SecretKey) Serialize() []byte { 173 | buf := make([]byte, C.mclBn_getFpByteSize()) 174 | // #nosec 175 | n := C.blsSecretKeySerialize(unsafe.Pointer(&buf[0]), C.mclSize(len(buf)), &sec.v) 176 | if n == 0 { 177 | panic("err blsSecretKeySerialize") 178 | } 179 | return buf[:n] 180 | } 181 | 182 | // Deserialize -- 183 | func (sec *SecretKey) Deserialize(buf []byte) error { 184 | // #nosec 185 | n := C.blsSecretKeyDeserialize(&sec.v, getPointer(buf), C.mclSize(len(buf))) 186 | if n == 0 || int(n) != len(buf) { 187 | return fmt.Errorf("err blsSecretKeyDeserialize %x", buf) 188 | } 189 | return nil 190 | } 191 | 192 | // GetLittleEndian -- alias of Serialize 193 | func (sec *SecretKey) GetLittleEndian() []byte { 194 | return sec.Serialize() 195 | } 196 | 197 | // SetLittleEndian -- 198 | func (sec *SecretKey) SetLittleEndian(buf []byte) error { 199 | // #nosec 200 | err := C.blsSecretKeySetLittleEndian(&sec.v, getPointer(buf), C.mclSize(len(buf))) 201 | if err != 0 { 202 | return fmt.Errorf("err blsSecretKeySetLittleEndian %x", err) 203 | } 204 | return nil 205 | } 206 | 207 | // SetLittleEndianMod -- 208 | func (sec *SecretKey) SetLittleEndianMod(buf []byte) error { 209 | // #nosec 210 | err := C.blsSecretKeySetLittleEndianMod(&sec.v, getPointer(buf), C.mclSize(len(buf))) 211 | if err != 0 { 212 | return fmt.Errorf("err blsSecretKeySetLittleEndianMod %x", err) 213 | } 214 | return nil 215 | } 216 | 217 | // SerializeToHexStr -- 218 | func (sec *SecretKey) SerializeToHexStr() string { 219 | return hex.EncodeToString(sec.Serialize()) 220 | } 221 | 222 | // DeserializeHexStr -- 223 | func (sec *SecretKey) DeserializeHexStr(s string) error { 224 | a, err := hex2byte(s) 225 | if err != nil { 226 | return err 227 | } 228 | return sec.Deserialize(a) 229 | } 230 | 231 | // GetHexString -- 232 | func (sec *SecretKey) GetHexString() string { 233 | buf := make([]byte, 2048) 234 | // #nosec 235 | n := C.blsSecretKeyGetHexStr((*C.char)(unsafe.Pointer(&buf[0])), C.mclSize(len(buf)), &sec.v) 236 | if n == 0 { 237 | panic("err blsSecretKeyGetHexStr") 238 | } 239 | return string(buf[:n]) 240 | } 241 | 242 | // GetDecString -- 243 | func (sec *SecretKey) GetDecString() string { 244 | buf := make([]byte, 2048) 245 | // #nosec 246 | n := C.blsSecretKeyGetDecStr((*C.char)(unsafe.Pointer(&buf[0])), C.mclSize(len(buf)), &sec.v) 247 | if n == 0 { 248 | panic("err blsSecretKeyGetDecStr") 249 | } 250 | return string(buf[:n]) 251 | } 252 | 253 | // SetHexString -- 254 | func (sec *SecretKey) SetHexString(s string) error { 255 | buf := []byte(s) 256 | // #nosec 257 | err := C.blsSecretKeySetHexStr(&sec.v, (*C.char)(getPointer(buf)), C.mclSize(len(buf))) 258 | if err != 0 { 259 | return fmt.Errorf("err blsSecretKeySetHexStr %s", s) 260 | } 261 | return nil 262 | } 263 | 264 | // SetDecString -- 265 | func (sec *SecretKey) SetDecString(s string) error { 266 | buf := []byte(s) 267 | // #nosec 268 | err := C.blsSecretKeySetDecStr(&sec.v, (*C.char)(getPointer(buf)), C.mclSize(len(buf))) 269 | if err != 0 { 270 | return fmt.Errorf("err blsSecretKeySetDecStr %s", s) 271 | } 272 | return nil 273 | } 274 | 275 | // IsEqual -- 276 | func (sec *SecretKey) IsEqual(rhs *SecretKey) bool { 277 | if sec == nil || rhs == nil { 278 | return false 279 | } 280 | return C.blsSecretKeyIsEqual(&sec.v, &rhs.v) == 1 281 | } 282 | 283 | // IsZero -- 284 | func (sec *SecretKey) IsZero() bool { 285 | return C.blsSecretKeyIsZero(&sec.v) == 1 286 | } 287 | 288 | // SetByCSPRNG -- 289 | func (sec *SecretKey) SetByCSPRNG() { 290 | err := C.blsSecretKeySetByCSPRNG(&sec.v) 291 | if err != 0 { 292 | panic("err blsSecretKeySetByCSPRNG") 293 | } 294 | if sec.IsZero() { 295 | panic("err blsSecretKeySetByCSPRNG zero") 296 | } 297 | } 298 | 299 | // Add -- 300 | func (sec *SecretKey) Add(rhs *SecretKey) { 301 | C.blsSecretKeyAdd(&sec.v, &rhs.v) 302 | } 303 | 304 | // GetMasterSecretKey -- 305 | func (sec *SecretKey) GetMasterSecretKey(k int) (msk []SecretKey) { 306 | msk = make([]SecretKey, k) 307 | msk[0] = *sec 308 | for i := 1; i < k; i++ { 309 | msk[i].SetByCSPRNG() 310 | } 311 | return msk 312 | } 313 | 314 | // GetMasterPublicKey -- 315 | func GetMasterPublicKey(msk []SecretKey) (mpk []PublicKey) { 316 | n := len(msk) 317 | mpk = make([]PublicKey, n) 318 | for i := 0; i < n; i++ { 319 | mpk[i] = *msk[i].GetPublicKey() 320 | } 321 | return mpk 322 | } 323 | 324 | // Set -- 325 | func (sec *SecretKey) Set(msk []SecretKey, id *ID) error { 326 | if len(msk) == 0 { 327 | return fmt.Errorf("Set zero mask") 328 | } 329 | // #nosec 330 | ret := C.blsSecretKeyShare(&sec.v, &msk[0].v, (C.mclSize)(len(msk)), &id.v) 331 | if ret != 0 { 332 | return fmt.Errorf("err blsSecretKeyShare") 333 | } 334 | return nil 335 | } 336 | 337 | // Recover -- 338 | func (sec *SecretKey) Recover(secVec []SecretKey, idVec []ID) error { 339 | n := len(secVec) 340 | if n == 0 { 341 | return fmt.Errorf("Recover zero secVec") 342 | } 343 | if n != len(idVec) { 344 | return fmt.Errorf("err SecretKey.Recover bad size") 345 | } 346 | // #nosec 347 | ret := C.blsSecretKeyRecover(&sec.v, &secVec[0].v, (*C.blsId)(&idVec[0].v), (C.mclSize)(n)) 348 | if ret != 0 { 349 | return fmt.Errorf("err blsSecretKeyRecover") 350 | } 351 | return nil 352 | } 353 | 354 | // GetPop -- 355 | func (sec *SecretKey) GetPop() (sig *Sign) { 356 | sig = new(Sign) 357 | C.blsGetPop(&sig.v, &sec.v) 358 | return sig 359 | } 360 | 361 | // PublicKey -- 362 | type PublicKey struct { 363 | v C.blsPublicKey 364 | } 365 | 366 | // PublicKeys .. 367 | type PublicKeys []PublicKey 368 | 369 | // JSON provides a JSON string dump of slice of PublicKeys in Hexformat 370 | func (keys PublicKeys) JSON() string { 371 | type T struct { 372 | Count int `json:"count"` 373 | PublicKeys []string `json:"public-keys"` 374 | } 375 | t := T{len(keys), make([]string, len(keys))} 376 | for i := range keys { 377 | t.PublicKeys[i] = keys[i].SerializeToHexStr() 378 | } 379 | b, _ := json.Marshal(t) 380 | return string(b) 381 | } 382 | 383 | // Serialize -- 384 | func (pub *PublicKey) Serialize() []byte { 385 | buf := make([]byte, C.blsGetSerializedPublicKeyByteSize()) 386 | // #nosec 387 | n := C.blsPublicKeySerialize(unsafe.Pointer(&buf[0]), C.mclSize(len(buf)), &pub.v) 388 | if n == 0 { 389 | panic("err blsPublicKeySerialize") 390 | } 391 | return buf[:n] 392 | } 393 | 394 | // Deserialize -- 395 | func (pub *PublicKey) Deserialize(buf []byte) error { 396 | // #nosec 397 | n := C.blsPublicKeyDeserialize(&pub.v, getPointer(buf), C.mclSize(len(buf))) 398 | if n == 0 || int(n) != len(buf) { 399 | return fmt.Errorf("err blsPublicKeyDeserialize %x", buf) 400 | } 401 | return nil 402 | } 403 | 404 | // SerializeToHexStr -- 405 | func (pub *PublicKey) SerializeToHexStr() string { 406 | return hex.EncodeToString(pub.Serialize()) 407 | } 408 | 409 | // DeserializeHexStr -- 410 | func (pub *PublicKey) DeserializeHexStr(s string) error { 411 | a, err := hex2byte(s) 412 | if err != nil { 413 | return err 414 | } 415 | return pub.Deserialize(a) 416 | } 417 | 418 | // GetHexString -- 419 | func (pub *PublicKey) GetHexString() string { 420 | buf := make([]byte, 2048) 421 | // #nosec 422 | n := C.blsPublicKeyGetHexStr((*C.char)(unsafe.Pointer(&buf[0])), C.mclSize(len(buf)), &pub.v) 423 | if n == 0 { 424 | panic("err blsPublicKeyGetHexStr") 425 | } 426 | return string(buf[:n]) 427 | } 428 | 429 | // SetHexString -- 430 | func (pub *PublicKey) SetHexString(s string) error { 431 | buf := []byte(s) 432 | // #nosec 433 | err := C.blsPublicKeySetHexStr(&pub.v, (*C.char)(getPointer(buf)), C.mclSize(len(buf))) 434 | if err != 0 { 435 | return fmt.Errorf("err blsPublicKeySetHexStr %s", s) 436 | } 437 | return nil 438 | } 439 | 440 | // IsEqual -- 441 | func (pub *PublicKey) IsEqual(rhs *PublicKey) bool { 442 | if pub == nil || rhs == nil { 443 | return false 444 | } 445 | return C.blsPublicKeyIsEqual(&pub.v, &rhs.v) == 1 446 | } 447 | 448 | // IsZero -- 449 | func (pub *PublicKey) IsZero() bool { 450 | return C.blsPublicKeyIsZero(&pub.v) == 1 451 | } 452 | 453 | // Add -- 454 | func (pub *PublicKey) Add(rhs *PublicKey) { 455 | C.blsPublicKeyAdd(&pub.v, &rhs.v) 456 | } 457 | 458 | // Set -- 459 | func (pub *PublicKey) Set(mpk []PublicKey, id *ID) error { 460 | if len(mpk) == 0 { 461 | return fmt.Errorf("Set zero mpk") 462 | } 463 | // #nosec 464 | ret := C.blsPublicKeyShare(&pub.v, &mpk[0].v, (C.mclSize)(len(mpk)), &id.v) 465 | if ret != 0 { 466 | return fmt.Errorf("err blsPublicKeyShare") 467 | } 468 | return nil 469 | } 470 | 471 | // Recover -- 472 | func (pub *PublicKey) Recover(pubVec []PublicKey, idVec []ID) error { 473 | n := len(pubVec) 474 | if n == 0 { 475 | return fmt.Errorf("Recover zero pubVec") 476 | } 477 | if n != len(idVec) { 478 | return fmt.Errorf("err PublicKey.Recover bad size") 479 | } 480 | // #nosec 481 | ret := C.blsPublicKeyRecover(&pub.v, &pubVec[0].v, (*C.blsId)(&idVec[0].v), (C.mclSize)(n)) 482 | if ret != 0 { 483 | return fmt.Errorf("err blsPublicKeyRecover") 484 | } 485 | return nil 486 | } 487 | 488 | // Sign -- 489 | type Sign struct { 490 | v C.blsSignature 491 | } 492 | 493 | // Serialize -- 494 | func (sig *Sign) Serialize() []byte { 495 | buf := make([]byte, C.blsGetSerializedSignatureByteSize()) 496 | // #nosec 497 | n := C.blsSignatureSerialize(unsafe.Pointer(&buf[0]), C.mclSize(len(buf)), &sig.v) 498 | if n == 0 { 499 | panic("err blsSignatureSerialize") 500 | } 501 | return buf[:n] 502 | } 503 | 504 | // Deserialize -- 505 | func (sig *Sign) Deserialize(buf []byte) error { 506 | // #nosec 507 | n := C.blsSignatureDeserialize(&sig.v, getPointer(buf), C.mclSize(len(buf))) 508 | if n == 0 || int(n) != len(buf) { 509 | return fmt.Errorf("err blsSignatureDeserialize %x", buf) 510 | } 511 | return nil 512 | } 513 | 514 | // SerializeToHexStr -- 515 | func (sig *Sign) SerializeToHexStr() string { 516 | return hex.EncodeToString(sig.Serialize()) 517 | } 518 | 519 | // DeserializeHexStr -- 520 | func (sig *Sign) DeserializeHexStr(s string) error { 521 | a, err := hex2byte(s) 522 | if err != nil { 523 | return err 524 | } 525 | return sig.Deserialize(a) 526 | } 527 | 528 | // GetHexString -- 529 | func (sig *Sign) GetHexString() string { 530 | buf := make([]byte, 2048) 531 | // #nosec 532 | n := C.blsSignatureGetHexStr((*C.char)(unsafe.Pointer(&buf[0])), C.mclSize(len(buf)), &sig.v) 533 | if n == 0 { 534 | panic("err blsSignatureGetHexStr") 535 | } 536 | return string(buf[:n]) 537 | } 538 | 539 | // SetHexString -- 540 | func (sig *Sign) SetHexString(s string) error { 541 | buf := []byte(s) 542 | // #nosec 543 | err := C.blsSignatureSetHexStr(&sig.v, (*C.char)(getPointer(buf)), C.mclSize(len(buf))) 544 | if err != 0 { 545 | return fmt.Errorf("err blsSignatureSetHexStr %s", s) 546 | } 547 | return nil 548 | } 549 | 550 | // IsEqual -- 551 | func (sig *Sign) IsEqual(rhs *Sign) bool { 552 | if sig == nil || rhs == nil { 553 | return false 554 | } 555 | return C.blsSignatureIsEqual(&sig.v, &rhs.v) == 1 556 | } 557 | 558 | // IsZero -- 559 | func (sig *Sign) IsZero() bool { 560 | return C.blsSignatureIsZero(&sig.v) == 1 561 | } 562 | 563 | // GetPublicKey -- 564 | func (sec *SecretKey) GetPublicKey() (pub *PublicKey) { 565 | pub = new(PublicKey) 566 | C.blsGetPublicKey(&pub.v, &sec.v) 567 | return pub 568 | } 569 | 570 | // GetSafePublicKey -- error if sec is zero 571 | func (sec *SecretKey) GetSafePublicKey() (pub *PublicKey, err error) { 572 | if sec.IsZero() { 573 | return nil, fmt.Errorf("sec is zero") 574 | } 575 | pub = new(PublicKey) 576 | C.blsGetPublicKey(&pub.v, &sec.v) 577 | return pub, nil 578 | } 579 | 580 | // Sign -- Constant Time version 581 | func (sec *SecretKey) Sign(m string) (sig *Sign) { 582 | sig = new(Sign) 583 | buf := []byte(m) 584 | // #nosec 585 | C.blsSign(&sig.v, &sec.v, getPointer(buf), C.mclSize(len(buf))) 586 | return sig 587 | } 588 | 589 | // Add -- 590 | func (sig *Sign) Add(rhs *Sign) { 591 | C.blsSignatureAdd(&sig.v, &rhs.v) 592 | } 593 | 594 | // Recover -- 595 | func (sig *Sign) Recover(sigVec []Sign, idVec []ID) error { 596 | if len(sigVec) == 0 { 597 | return fmt.Errorf("Recover zero sigVec") 598 | } 599 | if len(sigVec) != len(idVec) { 600 | return fmt.Errorf("err Sign.Recover bad size") 601 | } 602 | // #nosec 603 | ret := C.blsSignatureRecover(&sig.v, &sigVec[0].v, (*C.blsId)(&idVec[0].v), (C.mclSize)(len(idVec))) 604 | if ret != 0 { 605 | return fmt.Errorf("err blsSignatureRecover") 606 | } 607 | return nil 608 | } 609 | 610 | // Verify -- 611 | func (sig *Sign) Verify(pub *PublicKey, m string) bool { 612 | if sig == nil || pub == nil { 613 | return false 614 | } 615 | buf := []byte(m) 616 | // #nosec 617 | return C.blsVerify(&sig.v, &pub.v, getPointer(buf), C.mclSize(len(buf))) == 1 618 | } 619 | 620 | func bool2int(b bool) C.int { 621 | if b { 622 | return 1 623 | } 624 | return 0 625 | } 626 | 627 | // VerifySignatureOrder -- 628 | func VerifySignatureOrder(doVerify bool) { 629 | C.blsSignatureVerifyOrder(bool2int(doVerify)) 630 | } 631 | 632 | // VerifyPublicKeyOrder -- 633 | func VerifyPublicKeyOrder(doVerify bool) { 634 | C.blsPublicKeyVerifyOrder(bool2int(doVerify)) 635 | } 636 | 637 | // IsValidOrder -- 638 | func (pub *PublicKey) IsValidOrder() bool { 639 | return C.blsPublicKeyIsValidOrder(&pub.v) == 1 640 | } 641 | 642 | // IsValidOrder -- 643 | func (sig *Sign) IsValidOrder() bool { 644 | return C.blsSignatureIsValidOrder(&sig.v) == 1 645 | } 646 | 647 | // VerifyPop -- 648 | func (sig *Sign) VerifyPop(pub *PublicKey) bool { 649 | if sig == nil || pub == nil { 650 | return false 651 | } 652 | return C.blsVerifyPop(&sig.v, &pub.v) == 1 653 | } 654 | 655 | // DHKeyExchange -- 656 | func DHKeyExchange(sec *SecretKey, pub *PublicKey) (out PublicKey) { 657 | C.blsDHKeyExchange(&out.v, &sec.v, &pub.v) 658 | return out 659 | } 660 | 661 | // HashAndMapToSignature -- 662 | func HashAndMapToSignature(buf []byte) *Sign { 663 | sig := new(Sign) 664 | // #nosec 665 | err := C.blsHashToSignature(&sig.v, getPointer(buf), C.mclSize(len(buf))) 666 | if err != 0 { 667 | return nil 668 | } 669 | return sig 670 | } 671 | 672 | // VerifyPairing -- 673 | func VerifyPairing(X *Sign, Y *Sign, pub *PublicKey) bool { 674 | if X == nil || Y == nil || pub == nil { 675 | return false 676 | } 677 | return C.blsVerifyPairing(&X.v, &Y.v, &pub.v) == 1 678 | } 679 | 680 | // SignHash -- 681 | func (sec *SecretKey) SignHash(hash []byte) (sig *Sign) { 682 | sig = new(Sign) 683 | // #nosec 684 | err := C.blsSignHash(&sig.v, &sec.v, getPointer(hash), C.mclSize(len(hash))) 685 | if err == 0 { 686 | return sig 687 | } 688 | return nil 689 | } 690 | 691 | // VerifyHash -- 692 | func (sig *Sign) VerifyHash(pub *PublicKey, hash []byte) bool { 693 | if pub == nil { 694 | return false 695 | } 696 | // #nosec 697 | return C.blsVerifyHash(&sig.v, &pub.v, getPointer(hash), C.mclSize(len(hash))) == 1 698 | } 699 | 700 | func min(x, y int) int { 701 | if x < y { 702 | return x 703 | } 704 | return y 705 | } 706 | 707 | // VerifyAggregateHashes -- 708 | func (sig *Sign) VerifyAggregateHashes(pubVec []PublicKey, hash [][]byte) bool { 709 | if pubVec == nil { 710 | return false 711 | } 712 | n := len(hash) 713 | if n == 0 || len(pubVec) != n { 714 | return false 715 | } 716 | hashByte := len(hash[0]) 717 | if hashByte == 0 { 718 | return false 719 | } 720 | h := make([]byte, n*hashByte) 721 | for i := 0; i < n; i++ { 722 | hn := len(hash[i]) 723 | copy(h[i*hashByte:(i+1)*hashByte], hash[i][0:min(hn, hashByte)]) 724 | } 725 | return C.blsVerifyAggregatedHashes(&sig.v, &pubVec[0].v, unsafe.Pointer(&h[0]), C.mclSize(hashByte), C.mclSize(n)) == 1 726 | } 727 | 728 | // SignatureVerifyOrder -- 729 | // check the correctness of the order of signature in deserialize if true 730 | func SignatureVerifyOrder(doVerify bool) { 731 | var b = 0 732 | if doVerify { 733 | b = 1 734 | } 735 | C.blsSignatureVerifyOrder(C.int(b)) 736 | } 737 | 738 | // SignByte -- 739 | func (sec *SecretKey) SignByte(msg []byte) (sig *Sign) { 740 | sig = new(Sign) 741 | // #nosec 742 | C.blsSign(&sig.v, &sec.v, getPointer(msg), C.mclSize(len(msg))) 743 | return sig 744 | } 745 | 746 | // VerifyByte -- 747 | func (sig *Sign) VerifyByte(pub *PublicKey, msg []byte) bool { 748 | if sig == nil || pub == nil { 749 | return false 750 | } 751 | // #nosec 752 | return C.blsVerify(&sig.v, &pub.v, getPointer(msg), C.mclSize(len(msg))) == 1 753 | } 754 | 755 | // Aggregate -- 756 | func (sig *Sign) Aggregate(sigVec []Sign) { 757 | var p *C.blsSignature 758 | if len(sigVec) == 0 { 759 | p = nil 760 | } else { 761 | p = &sigVec[0].v 762 | } 763 | C.blsAggregateSignature(&sig.v, p, C.mclSize(len(sigVec))) 764 | } 765 | 766 | // FastAggregateVerify -- 767 | func (sig *Sign) FastAggregateVerify(pubVec []PublicKey, msg []byte) bool { 768 | if pubVec == nil || len(pubVec) == 0 { 769 | return false 770 | } 771 | n := len(pubVec) 772 | return C.blsFastAggregateVerify(&sig.v, &pubVec[0].v, C.mclSize(n), getPointer(msg), C.mclSize(len(msg))) == 1 773 | } 774 | 775 | /// 776 | 777 | var sRandReader io.Reader 778 | 779 | func createSlice(buf *C.char, n C.uint) []byte { 780 | size := int(n) 781 | return (*[1 << 30]byte)(unsafe.Pointer(buf))[:size:size] 782 | } 783 | 784 | // this function can't be put in callback.go 785 | //export wrapReadRandGo 786 | func wrapReadRandGo(buf *C.char, n C.uint) C.uint { 787 | slice := createSlice(buf, n) 788 | ret, err := sRandReader.Read(slice) 789 | if ret == int(n) && err == nil { 790 | return n 791 | } 792 | return 0 793 | } 794 | 795 | // SetRandFunc -- 796 | func SetRandFunc(randReader io.Reader) { 797 | sRandReader = randReader 798 | if randReader != nil { 799 | C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(C.wrapReadRandCgo))) 800 | } else { 801 | // use default random generator 802 | C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(nil))) 803 | } 804 | } 805 | 806 | // GetGeneratorOfPublicKey - 807 | func GetGeneratorOfPublicKey(pub *PublicKey) { 808 | C.blsGetGeneratorOfPublicKey(&pub.v) 809 | } 810 | 811 | // SetGeneratorOfPublicKey - 812 | func SetGeneratorOfPublicKey(pub *PublicKey) error { 813 | if C.blsSetGeneratorOfPublicKey(&pub.v) != 0 { 814 | return fmt.Errorf("bad public key") 815 | } 816 | return nil 817 | } 818 | 819 | // keep for backward compatibility 820 | func BlsGetGeneratorOfPublicKey(pub *PublicKey) { 821 | GetGeneratorOfPublicKey(pub) 822 | } 823 | -------------------------------------------------------------------------------- /bls/bls_test.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | // e(P1, Q1) == e(P2, Q2) 9 | func comparePairing1(P1 *G1, Q1 *G2, P2 *G1, Q2 *G2) bool { 10 | var e1, e2 GT 11 | Pairing(&e1, P1, Q1) 12 | Pairing(&e2, P2, Q2) 13 | return e1.IsEqual(&e2) 14 | } 15 | 16 | // FinalExp(ML(P1, Q1) ML(-P2, Q2)) == 1 17 | func comparePairing2(P1 *G1, Q1 *G2, P2 *G1, Q2 *G2) bool { 18 | var e1, e2 GT 19 | MillerLoop(&e1, P1, Q1) 20 | var negP2 G1 21 | G1Neg(&negP2, P2) 22 | MillerLoop(&e2, &negP2, Q2) 23 | GTMul(&e1, &e1, &e2) 24 | FinalExp(&e1, &e1) 25 | return e1.IsOne() 26 | } 27 | 28 | // FinalExp(MLvec(P1, Q1, -P2, Q2)) == 1 29 | func comparePairing3(P1 *G1, Q1 *G2, P2 *G1, Q2 *G2) bool { 30 | var e GT 31 | v1 := make([]G1, 2) 32 | v2 := make([]G2, 2) 33 | v1[0] = *P1 34 | G1Neg(&v1[1], P2) 35 | v2[0] = *Q1 36 | v2[1] = *Q2 37 | MillerLoopVec(&e, v1, v2) 38 | FinalExp(&e, &e) 39 | return e.IsOne() 40 | } 41 | 42 | // set (P1, Q1, P2, Q2) s.t. e(P1, Q1) == e(P2, Q2) 43 | func initPQ(P1 *G1, Q1 *G2, P2 *G1, Q2 *G2) { 44 | P1.HashAndMapTo([]byte("abc")) 45 | Q1.HashAndMapTo([]byte("abc")) 46 | var a Fr 47 | var rev Fr 48 | a.SetInt64(123) 49 | FrInv(&rev, &a) 50 | G1Mul(P2, P1, &a) 51 | G2Mul(Q2, Q1, &rev) 52 | } 53 | 54 | func TestSign(t *testing.T) { 55 | Init(BLS12_381) 56 | var sec SecretKey 57 | sec.SetByCSPRNG() 58 | fmt.Printf("sec:%s\n", sec.SerializeToHexStr()) 59 | pub := sec.GetPublicKey() 60 | fmt.Printf("pub:%s\n", pub.SerializeToHexStr()) 61 | msgTbl := []string{"abc", "def", "123"} 62 | n := len(msgTbl) 63 | sigVec := make([]*Sign, n) 64 | for i := 0; i < n; i++ { 65 | m := msgTbl[i] 66 | sigVec[i] = sec.Sign(m) 67 | fmt.Printf("%d. sign(%s)=%s\n", i, m, sigVec[i].SerializeToHexStr()) 68 | } 69 | agg := sigVec[0] 70 | for i := 1; i < n; i++ { 71 | agg.Add(sigVec[i]) 72 | } 73 | hashPt := HashAndMapToSignature([]byte(msgTbl[0])) 74 | for i := 1; i < n; i++ { 75 | hashPt.Add(HashAndMapToSignature([]byte(msgTbl[i]))) 76 | } 77 | if !VerifyPairing(agg, hashPt, pub) { 78 | t.Error("VerifyPairing") 79 | } 80 | } 81 | 82 | func TestPairing(t *testing.T) { 83 | Init(BLS12_381) 84 | var P1, P2 G1 85 | var Q1, Q2 G2 86 | initPQ(&P1, &Q1, &P2, &Q2) 87 | var b1, b2, b3 bool 88 | b1 = comparePairing1(&P1, &Q1, &P2, &Q2) 89 | b2 = comparePairing2(&P1, &Q1, &P2, &Q2) 90 | b3 = comparePairing3(&P1, &Q1, &P2, &Q2) 91 | if !(b1 && b2 && b3) { 92 | t.Error("must be true") 93 | } 94 | G1Dbl(&P1, &P1) 95 | // e(P1, Q1) != e(P2, Q2) 96 | b1 = comparePairing1(&P1, &Q1, &P2, &Q2) 97 | b2 = comparePairing2(&P1, &Q1, &P2, &Q2) 98 | b3 = comparePairing3(&P1, &Q1, &P2, &Q2) 99 | if b1 || b2 || b3 { 100 | t.Error("must be false") 101 | } 102 | } 103 | 104 | func TestCast(t *testing.T) { 105 | Init(BLS12_381) 106 | var sec SecretKey 107 | sec.SetByCSPRNG() 108 | { 109 | x := *CastFromSecretKey(&sec) 110 | sec2 := *CastToSecretKey(&x) 111 | if !sec.IsEqual(&sec2) { 112 | t.Error("sec is not equal") 113 | } 114 | } 115 | pub := *sec.GetPublicKey() 116 | g2 := *CastFromPublicKey(&pub) 117 | G2Add(&g2, &g2, &g2) 118 | pub.Add(&pub) 119 | if !pub.IsEqual(CastToPublicKey(&g2)) { 120 | t.Error("pub not equal") 121 | } 122 | sig := sec.Sign("abc") 123 | g1 := *CastFromSign(sig) 124 | G1Add(&g1, &g1, &g1) 125 | sig.Add(sig) 126 | if !sig.IsEqual(CastToSign(&g1)) { 127 | t.Error("sig not equal") 128 | } 129 | } 130 | 131 | func BenchmarkPairing(b *testing.B) { 132 | Init(BLS12_381) 133 | var P G1 134 | var Q G2 135 | var e GT 136 | P.HashAndMapTo([]byte("abc")) 137 | Q.HashAndMapTo([]byte("abc")) 138 | b.ResetTimer() 139 | for i := 0; i < b.N; i++ { 140 | Pairing(&e, &P, &Q) 141 | } 142 | } 143 | 144 | func BenchmarkPairing1(b *testing.B) { 145 | var P1, P2 G1 146 | var Q1, Q2 G2 147 | initPQ(&P1, &Q1, &P2, &Q2) 148 | b.ResetTimer() 149 | for i := 0; i < b.N; i++ { 150 | comparePairing1(&P1, &Q1, &P2, &Q2) 151 | } 152 | } 153 | 154 | func BenchmarkPairing2(b *testing.B) { 155 | var P1, P2 G1 156 | var Q1, Q2 G2 157 | initPQ(&P1, &Q1, &P2, &Q2) 158 | b.ResetTimer() 159 | for i := 0; i < b.N; i++ { 160 | comparePairing2(&P1, &Q1, &P2, &Q2) 161 | } 162 | } 163 | 164 | func BenchmarkPairing3(b *testing.B) { 165 | var P1, P2 G1 166 | var Q1, Q2 G2 167 | initPQ(&P1, &Q1, &P2, &Q2) 168 | b.ResetTimer() 169 | for i := 0; i < b.N; i++ { 170 | comparePairing3(&P1, &Q1, &P2, &Q2) 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /bls/callback.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | /* 4 | // exported from bls.go 5 | unsigned int wrapReadRandGo(void *buf, unsigned int n); 6 | int wrapReadRandCgo(void *self, void *buf, unsigned int n) 7 | { 8 | (void)self; 9 | return wrapReadRandGo(buf, n); 10 | } 11 | */ 12 | import "C" 13 | -------------------------------------------------------------------------------- /bls/cast.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | // SecretKey 8 | 9 | func CastFromSecretKey(in *SecretKey) *Fr { 10 | return (*Fr)(unsafe.Pointer(in)) 11 | } 12 | 13 | func CastToSecretKey(in *Fr) *SecretKey { 14 | return (*SecretKey)(unsafe.Pointer(in)) 15 | } 16 | 17 | // PublicKey 18 | 19 | func CastFromPublicKey(in *PublicKey) *G2 { 20 | return (*G2)(unsafe.Pointer(in)) 21 | } 22 | 23 | func CastToPublicKey(in *G2) *PublicKey { 24 | return (*PublicKey)(unsafe.Pointer(in)) 25 | } 26 | 27 | // Sign 28 | 29 | func CastFromSign(in *Sign) *G1 { 30 | return (*G1)(unsafe.Pointer(in)) 31 | } 32 | 33 | func CastToSign(in *G1) *Sign { 34 | return (*Sign)(unsafe.Pointer(in)) 35 | } 36 | -------------------------------------------------------------------------------- /bls/dfinity_test.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func InitForDFINITY() error { 8 | err := Init(BLS12_381) 9 | if err != nil { 10 | return err 11 | } 12 | // set Ethereum serialization format. 13 | SetETHserialization(true) 14 | err = SetMapToMode(IRTF) 15 | if err != nil { 16 | return err 17 | } 18 | // set the generator of G2. see https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#section-4.2.1 19 | var gen PublicKey 20 | g2genStr := "1 0x24aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be" 21 | err = gen.SetHexString(g2genStr) 22 | if err != nil { 23 | return err 24 | } 25 | err = SetGeneratorOfPublicKey(&gen) 26 | if err != nil { 27 | return err 28 | } 29 | dst := "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" 30 | err = SetDstG1(dst) 31 | if err != nil { 32 | return err 33 | } 34 | return nil 35 | } 36 | 37 | func TestDFINITY(t *testing.T) { 38 | if InitForDFINITY() != nil { 39 | t.Error("InitForDFINITY") 40 | } 41 | 42 | // test of https://github.com/dfinity/agent-js/blob/5214dc1fc4b9b41f023a88b1228f04d2f2536987/packages/bls-verify/src/index.test.ts#L101 43 | pubStr := "a7623a93cdb56c4d23d99c14216afaab3dfd6d4f9eb3db23d038280b6d5cb2caaee2a19dd92c9df7001dede23bf036bc0f33982dfb41e8fa9b8e96b5dc3e83d55ca4dd146c7eb2e8b6859cb5a5db815db86810b8d12cee1588b5dbf34a4dc9a5" 44 | sigStr := "b89e13a212c830586eaa9ad53946cd968718ebecc27eda849d9232673dcd4f440e8b5df39bf14a88048c15e16cbcaabe" 45 | var pub PublicKey 46 | var sig Sign 47 | if pub.DeserializeHexStr(pubStr) != nil { 48 | t.Error("pub.DeserializeHexStr") 49 | } 50 | if sig.DeserializeHexStr(sigStr) != nil { 51 | t.Error("sig.DeserializeHexStr") 52 | } 53 | if !sig.Verify(&pub, "hello") { 54 | t.Error("verify1") 55 | } 56 | if sig.Verify(&pub, "hallo") { 57 | t.Error("verify2") 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /bls/include/bls/bls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief C interface of bls.hpp 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #define MCLBN_NO_AUTOLINK 10 | #include 11 | 12 | #ifdef BLS_ETH 13 | #define BLS_COMPILER_TIME_VAR_ADJ 200 14 | /* 15 | error if BLS_ETH is inconsistently defined between library and exe 16 | */ 17 | #undef MCLBN_COMPILED_TIME_VAR 18 | #define MCLBN_COMPILED_TIME_VAR ((MCLBN_FR_UNIT_SIZE) * 10 + (MCLBN_FP_UNIT_SIZE) + BLS_COMPILER_TIME_VAR_ADJ) 19 | #endif 20 | 21 | #ifdef _WIN32 22 | #ifdef BLS_DONT_EXPORT 23 | #define BLS_DLL_API 24 | #else 25 | #ifdef BLS_DLL_EXPORT 26 | #define BLS_DLL_API __declspec(dllexport) 27 | #else 28 | #define BLS_DLL_API //__declspec(dllimport) 29 | #endif 30 | #endif 31 | #if defined(_MSC_VER) && !defined(BLS_NO_AUTOLINK) 32 | #if MCLBN_FP_UNIT_SIZE == 4 33 | #pragma comment(lib, "bls256.lib") 34 | #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 4) 35 | #pragma comment(lib, "bls384_256.lib") 36 | #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 6) 37 | #pragma comment(lib, "bls384.lib") 38 | #endif 39 | #endif 40 | #elif defined(__EMSCRIPTEN__) && !defined(BLS_DONT_EXPORT) 41 | #define BLS_DLL_API __attribute__((used)) 42 | #elif defined(__wasm__) && !defined(BLS_DONT_EXPORT) 43 | #define BLS_DLL_API __attribute__((visibility("default"))) 44 | #else 45 | #define BLS_DLL_API 46 | #endif 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | typedef struct { 53 | mclBnFr v; 54 | } blsId; 55 | 56 | typedef struct { 57 | mclBnFr v; 58 | } blsSecretKey; 59 | 60 | typedef struct { 61 | #ifdef BLS_ETH 62 | mclBnG1 v; 63 | #else 64 | mclBnG2 v; 65 | #endif 66 | } blsPublicKey; 67 | 68 | typedef struct { 69 | #ifdef BLS_ETH 70 | mclBnG2 v; 71 | #else 72 | mclBnG1 v; 73 | #endif 74 | } blsSignature; 75 | 76 | /* 77 | initialize this library 78 | call this once before using the other functions 79 | @param curve [in] enum value defined in mcl/bn.h 80 | @param compiledTimeVar [in] specify MCLBN_COMPILED_TIME_VAR, 81 | which macro is used to make sure that the values 82 | are the same when the library is built and used 83 | @return 0 if success 84 | @note blsInit() is not thread safe 85 | */ 86 | BLS_DLL_API int blsInit(int curve, int compiledTimeVar); 87 | 88 | /* 89 | use new eth 2.0 spec 90 | @return 0 if success 91 | @remark 92 | this functions and the spec may change until it is fixed 93 | the size of message <= 32 94 | */ 95 | #define BLS_ETH_MODE_OLD 0 96 | #define BLS_ETH_MODE_DRAFT_05 1 // 2020/Jan/30 97 | #define BLS_ETH_MODE_DRAFT_06 2 // 2020/Mar/15 98 | #define BLS_ETH_MODE_DRAFT_07 3 // 2020/May/13 99 | #define BLS_ETH_MODE_LATEST 3 100 | BLS_DLL_API int blsSetETHmode(int mode); 101 | 102 | /* 103 | set ETH serialization mode for BLS12-381 104 | @param ETHserialization [in] 1:enable, 0:disable 105 | @note ignore the flag if curve is not BLS12-381 106 | @note set in blsInit if BLS_ETH is defined 107 | */ 108 | BLS_DLL_API void blsSetETHserialization(int ETHserialization); 109 | 110 | /* 111 | set map-to-function to mode 112 | MCL_MAP_TO_MODE_ORIGINAL ; for backward compatibility 113 | MCL_MAP_TO_MODE_HASH_TO_CURVE ; irtf-cfrg-hash-to-curve 114 | return 0 if success else -1 115 | */ 116 | BLS_DLL_API int blsSetMapToMode(int mode); 117 | 118 | BLS_DLL_API void blsIdSetInt(blsId *id, int x); 119 | 120 | // sec = buf & (1 << bitLen(r)) - 1 121 | // if (sec >= r) sec &= (1 << (bitLen(r) - 1)) - 1 122 | // always return 0 123 | BLS_DLL_API int blsSecretKeySetLittleEndian(blsSecretKey *sec, const void *buf, mclSize bufSize); 124 | // return 0 if success (bufSize <= 64) else -1 125 | // set (buf mod r) to sec 126 | BLS_DLL_API int blsSecretKeySetLittleEndianMod(blsSecretKey *sec, const void *buf, mclSize bufSize); 127 | 128 | BLS_DLL_API void blsGetPublicKey(blsPublicKey *pub, const blsSecretKey *sec); 129 | 130 | // calculate the has of m and sign the hash 131 | BLS_DLL_API void blsSign(blsSignature *sig, const blsSecretKey *sec, const void *m, mclSize size); 132 | 133 | // return 1 if valid else 0 134 | // @remark return 0 if pub is zero for BLS_ETH 135 | BLS_DLL_API int blsVerify(const blsSignature *sig, const blsPublicKey *pub, const void *m, mclSize size); 136 | /* 137 | return 1 if blsVerify(&sigVec[i], &pubVec[i], &msgVec[i * msgSize]) returns 1 for all i = 0, ..., n-1 138 | @param randVec [in] non-zero randSize * n byte array 139 | @note for only BLS_ETH 140 | sig = sum_i sigVec[i] * randVec[i] 141 | pubVec[i] *= randVec[i] 142 | return blsAggregateVerifyNoCheck(sig, pubVec, msgVec, msgSize, n); 143 | @remark return 0 if some pubVec[i] is zero 144 | sigVec may be normalized 145 | */ 146 | BLS_DLL_API int blsMultiVerify(blsSignature *sigVec, const blsPublicKey *pubVec, const void *msgVec, mclSize msgSize, const void *randVec, mclSize randSize, mclSize n, int threadN); 147 | 148 | /* 149 | subroutine of blsMultiVerify 150 | e = prod_i millerLoop(pubVec[i] * randVec[i], Hash(msgVec[i])) 151 | aggSig = sum_i sigVec[i] * randVec[i] 152 | @remark set *e = 0 if some pubVec[i] is zero 153 | sigVec may be normalized 154 | */ 155 | BLS_DLL_API void blsMultiVerifySub(mclBnGT *e, blsSignature *aggSig, blsSignature *sigVec, const blsPublicKey *pubVec, const char *msg, mclSize msgSize, const char *randVec, mclSize randSize, mclSize n); 156 | 157 | /* 158 | subroutine of blsMultiVerify 159 | return FE(e * ML(P, -aggSig)) == 1 ? 1 : 0 160 | */ 161 | BLS_DLL_API int blsMultiVerifyFinal(const mclBnGT *e, const blsSignature *aggSig); 162 | 163 | // aggSig = sum of sigVec[0..n] 164 | BLS_DLL_API void blsAggregateSignature(blsSignature *aggSig, const blsSignature *sigVec, mclSize n); 165 | 166 | // verify(sig, sum of pubVec[0..n], msg) 167 | BLS_DLL_API int blsFastAggregateVerify(const blsSignature *sig, const blsPublicKey *pubVec, mclSize n, const void *msg, mclSize msgSize); 168 | 169 | /* 170 | all msg[i] has the same msgSize byte, so msgVec must have (msgSize * n) byte area 171 | verify prod e(H(pubVec[i], msgToG2[i]) == e(P, sig) 172 | @note CHECK that sig has the valid order, all msg are different each other before calling this 173 | */ 174 | BLS_DLL_API int blsAggregateVerifyNoCheck(const blsSignature *sig, const blsPublicKey *pubVec, const void *msgVec, mclSize msgSize, mclSize n); 175 | 176 | // return written byte size if success else 0 177 | BLS_DLL_API mclSize blsIdSerialize(void *buf, mclSize maxBufSize, const blsId *id); 178 | BLS_DLL_API mclSize blsSecretKeySerialize(void *buf, mclSize maxBufSize, const blsSecretKey *sec); 179 | BLS_DLL_API mclSize blsPublicKeySerialize(void *buf, mclSize maxBufSize, const blsPublicKey *pub); 180 | BLS_DLL_API mclSize blsSignatureSerialize(void *buf, mclSize maxBufSize, const blsSignature *sig); 181 | 182 | // return read byte size if success else 0 183 | BLS_DLL_API mclSize blsIdDeserialize(blsId *id, const void *buf, mclSize bufSize); 184 | BLS_DLL_API mclSize blsSecretKeyDeserialize(blsSecretKey *sec, const void *buf, mclSize bufSize); 185 | BLS_DLL_API mclSize blsPublicKeyDeserialize(blsPublicKey *pub, const void *buf, mclSize bufSize); 186 | BLS_DLL_API mclSize blsSignatureDeserialize(blsSignature *sig, const void *buf, mclSize bufSize); 187 | 188 | // return 1 if same else 0 189 | BLS_DLL_API int blsIdIsEqual(const blsId *lhs, const blsId *rhs); 190 | BLS_DLL_API int blsSecretKeyIsEqual(const blsSecretKey *lhs, const blsSecretKey *rhs); 191 | BLS_DLL_API int blsPublicKeyIsEqual(const blsPublicKey *lhs, const blsPublicKey *rhs); 192 | BLS_DLL_API int blsSignatureIsEqual(const blsSignature *lhs, const blsSignature *rhs); 193 | 194 | // return 1 if zero else 0 195 | BLS_DLL_API int blsIdIsZero(const blsId *x); 196 | BLS_DLL_API int blsSecretKeyIsZero(const blsSecretKey *x); 197 | BLS_DLL_API int blsPublicKeyIsZero(const blsPublicKey *x); 198 | BLS_DLL_API int blsSignatureIsZero(const blsSignature *x); 199 | 200 | // return 0 if success 201 | // make sec corresponding to id from {msk[0], ..., msk[k-1]} 202 | BLS_DLL_API int blsSecretKeyShare(blsSecretKey *sec, const blsSecretKey *msk, mclSize k, const blsId *id); 203 | // make pub corresponding to id from {mpk[0], ..., mpk[k-1]} 204 | BLS_DLL_API int blsPublicKeyShare(blsPublicKey *pub, const blsPublicKey *mpk, mclSize k, const blsId *id); 205 | 206 | // return 0 if success 207 | // recover sec from {(secVec[i], idVec[i]) for i = 0, ..., n-1} 208 | BLS_DLL_API int blsSecretKeyRecover(blsSecretKey *sec, const blsSecretKey *secVec, const blsId *idVec, mclSize n); 209 | // recover pub from {(pubVec[i], idVec[i]) for i = 0, ..., n-1} 210 | BLS_DLL_API int blsPublicKeyRecover(blsPublicKey *pub, const blsPublicKey *pubVec, const blsId *idVec, mclSize n); 211 | // recover sig from {(sigVec[i], idVec[i]) for i = 0, ..., n-1} 212 | BLS_DLL_API int blsSignatureRecover(blsSignature *sig, const blsSignature *sigVec, const blsId *idVec, mclSize n); 213 | 214 | // sec += rhs 215 | BLS_DLL_API void blsSecretKeyAdd(blsSecretKey *sec, const blsSecretKey *rhs); 216 | // pub += rhs 217 | BLS_DLL_API void blsPublicKeyAdd(blsPublicKey *pub, const blsPublicKey *rhs); 218 | // sig += rhs 219 | BLS_DLL_API void blsSignatureAdd(blsSignature *sig, const blsSignature *rhs); 220 | 221 | /* 222 | verify whether a point of an elliptic curve has order r 223 | This api affetcs setStr(), deserialize() for G2 on BN or G1/G2 on BLS12 224 | @param doVerify [in] does not verify if zero(default 1) 225 | Signature = G1, PublicKey = G2 226 | */ 227 | BLS_DLL_API void blsSignatureVerifyOrder(int doVerify); 228 | BLS_DLL_API void blsPublicKeyVerifyOrder(int doVerify); 229 | // deserialize under VerifyOrder(true) = deserialize under VerifyOrder(false) + IsValidOrder 230 | BLS_DLL_API int blsSignatureIsValidOrder(const blsSignature *sig); 231 | BLS_DLL_API int blsPublicKeyIsValidOrder(const blsPublicKey *pub); 232 | 233 | #ifndef BLS_MINIMUM_API 234 | 235 | /* 236 | verify X == sY by checking e(X, sQ) = e(Y, Q) 237 | @param X [in] 238 | @param Y [in] 239 | @param pub [in] pub = sQ 240 | @return 1 if e(X, pub) = e(Y, Q) else 0 241 | */ 242 | BLS_DLL_API int blsVerifyPairing(const blsSignature *X, const blsSignature *Y, const blsPublicKey *pub); 243 | 244 | /* 245 | sign the hash 246 | use the low (bitSize of r) - 1 bit of h 247 | return 0 if success else -1 248 | NOTE : return false if h is zero or c1 or -c1 value for BN254. see hashTest() in test/bls_test.hpp 249 | */ 250 | BLS_DLL_API int blsSignHash(blsSignature *sig, const blsSecretKey *sec, const void *h, mclSize size); 251 | // return 1 if valid 252 | BLS_DLL_API int blsVerifyHash(const blsSignature *sig, const blsPublicKey *pub, const void *h, mclSize size); 253 | 254 | /* 255 | verify aggSig with pubVec[0, n) and hVec[0, n) 256 | e(aggSig, Q) = prod_i e(hVec[i], pubVec[i]) 257 | return 1 if valid 258 | @note do not check duplication of hVec 259 | */ 260 | BLS_DLL_API int blsVerifyAggregatedHashes(const blsSignature *aggSig, const blsPublicKey *pubVec, const void *hVec, size_t sizeofHash, mclSize n); 261 | 262 | /* 263 | Uncompressed version of Serialize/Deserialize 264 | the buffer size is twice of Serialize/Deserialize 265 | */ 266 | BLS_DLL_API mclSize blsPublicKeySerializeUncompressed(void *buf, mclSize maxBufSize, const blsPublicKey *pub); 267 | BLS_DLL_API mclSize blsSignatureSerializeUncompressed(void *buf, mclSize maxBufSize, const blsSignature *sig); 268 | BLS_DLL_API mclSize blsPublicKeyDeserializeUncompressed(blsPublicKey *pub, const void *buf, mclSize bufSize); 269 | BLS_DLL_API mclSize blsSignatureDeserializeUncompressed(blsSignature *sig, const void *buf, mclSize bufSize); 270 | 271 | ///// to here only for BLS12-381 with BLS_ETH 272 | 273 | // sub 274 | BLS_DLL_API void blsSecretKeySub(blsSecretKey *sec, const blsSecretKey *rhs); 275 | BLS_DLL_API void blsPublicKeySub(blsPublicKey *pub, const blsPublicKey *rhs); 276 | BLS_DLL_API void blsSignatureSub(blsSignature *sig, const blsSignature *rhs); 277 | 278 | // neg 279 | BLS_DLL_API void blsSecretKeyNeg(blsSecretKey *x); 280 | BLS_DLL_API void blsPublicKeyNeg(blsPublicKey *x); 281 | BLS_DLL_API void blsSignatureNeg(blsSignature *x); 282 | 283 | // mul y *= x 284 | BLS_DLL_API void blsSecretKeyMul(blsSecretKey *y, const blsSecretKey *x); 285 | BLS_DLL_API void blsPublicKeyMul(blsPublicKey *y, const blsSecretKey *x); 286 | BLS_DLL_API void blsSignatureMul(blsSignature *y, const blsSecretKey *x); 287 | 288 | // x may be normalized, so it is not a const pointer 289 | BLS_DLL_API void blsPublicKeyMulVec(blsPublicKey *z, blsPublicKey *x, const blsSecretKey *y, mclSize n); 290 | BLS_DLL_API void blsSignatureMulVec(blsSignature *z, blsSignature *x, const blsSecretKey *y, mclSize n); 291 | 292 | // not thread safe version (old blsInit) 293 | BLS_DLL_API int blsInitNotThreadSafe(int curve, int compiledTimeVar); 294 | 295 | BLS_DLL_API mclSize blsGetOpUnitSize(void); 296 | // return strlen(buf) if success else 0 297 | BLS_DLL_API int blsGetCurveOrder(char *buf, mclSize maxBufSize); 298 | BLS_DLL_API int blsGetFieldOrder(char *buf, mclSize maxBufSize); 299 | 300 | // return serialized secretKey size 301 | BLS_DLL_API int blsGetSerializedSecretKeyByteSize(void); 302 | // return serialized publicKey size 303 | BLS_DLL_API int blsGetSerializedPublicKeyByteSize(void); 304 | // return serialized signature size 305 | BLS_DLL_API int blsGetSerializedSignatureByteSize(void); 306 | 307 | // return bytes for serialized G1(=Fp) 308 | BLS_DLL_API int blsGetG1ByteSize(void); 309 | 310 | // return bytes for serialized Fr 311 | BLS_DLL_API int blsGetFrByteSize(void); 312 | 313 | // get a generator of PublicKey 314 | BLS_DLL_API void blsGetGeneratorOfPublicKey(blsPublicKey *pub); 315 | // set a generator of PublicKey 316 | BLS_DLL_API int blsSetGeneratorOfPublicKey(const blsPublicKey *pub); 317 | 318 | // return 0 if success 319 | BLS_DLL_API int blsIdSetDecStr(blsId *id, const char *buf, mclSize bufSize); 320 | BLS_DLL_API int blsIdSetHexStr(blsId *id, const char *buf, mclSize bufSize); 321 | 322 | /* 323 | return strlen(buf) if success else 0 324 | buf is '\0' terminated 325 | */ 326 | BLS_DLL_API mclSize blsIdGetDecStr(char *buf, mclSize maxBufSize, const blsId *id); 327 | BLS_DLL_API mclSize blsIdGetHexStr(char *buf, mclSize maxBufSize, const blsId *id); 328 | 329 | // hash buf and set SecretKey 330 | BLS_DLL_API int blsHashToSecretKey(blsSecretKey *sec, const void *buf, mclSize bufSize); 331 | // hash buf and set Signature 332 | BLS_DLL_API int blsHashToSignature(blsSignature *sig, const void *buf, mclSize bufSize); 333 | #ifndef MCL_DONT_USE_CSPRNG 334 | /* 335 | set secretKey if system has /dev/urandom or CryptGenRandom 336 | return 0 if success else -1 337 | */ 338 | BLS_DLL_API int blsSecretKeySetByCSPRNG(blsSecretKey *sec); 339 | /* 340 | set user-defined random function for setByCSPRNG 341 | @param self [in] user-defined pointer 342 | @param readFunc [in] user-defined function, 343 | which writes random bufSize bytes to buf and returns bufSize if success else returns 0 344 | @note if self == 0 and readFunc == 0 then set default random function 345 | @note not threadsafe 346 | */ 347 | BLS_DLL_API void blsSetRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)); 348 | #endif 349 | 350 | BLS_DLL_API void blsGetPop(blsSignature *sig, const blsSecretKey *sec); 351 | 352 | BLS_DLL_API int blsVerifyPop(const blsSignature *sig, const blsPublicKey *pub); 353 | ////////////////////////////////////////////////////////////////////////// 354 | // the following apis will be removed 355 | 356 | // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r 357 | BLS_DLL_API int blsIdSetLittleEndian(blsId *id, const void *buf, mclSize bufSize); 358 | /* 359 | return written byte size if success else 0 360 | */ 361 | BLS_DLL_API mclSize blsIdGetLittleEndian(void *buf, mclSize maxBufSize, const blsId *id); 362 | 363 | // return 0 if success 364 | BLS_DLL_API int blsSecretKeySetDecStr(blsSecretKey *sec, const char *buf, mclSize bufSize); 365 | BLS_DLL_API int blsSecretKeySetHexStr(blsSecretKey *sec, const char *buf, mclSize bufSize); 366 | BLS_DLL_API int blsPublicKeySetHexStr(blsPublicKey *pub, const char *buf, mclSize bufSize); 367 | BLS_DLL_API int blsSignatureSetHexStr(blsSignature *sig, const char *buf, mclSize bufSize); 368 | /* 369 | return written byte size if success else 0 370 | */ 371 | BLS_DLL_API mclSize blsSecretKeyGetLittleEndian(void *buf, mclSize maxBufSize, const blsSecretKey *sec); 372 | /* 373 | return strlen(buf) if success else 0 374 | buf is '\0' terminated 375 | */ 376 | BLS_DLL_API mclSize blsSecretKeyGetDecStr(char *buf, mclSize maxBufSize, const blsSecretKey *sec); 377 | BLS_DLL_API mclSize blsSecretKeyGetHexStr(char *buf, mclSize maxBufSize, const blsSecretKey *sec); 378 | BLS_DLL_API mclSize blsPublicKeyGetHexStr(char *buf, mclSize maxBufSize, const blsPublicKey *pub); 379 | BLS_DLL_API mclSize blsSignatureGetHexStr(char *buf, mclSize maxBufSize, const blsSignature *sig); 380 | 381 | /* 382 | Diffie Hellman key exchange 383 | out = sec * pub 384 | */ 385 | BLS_DLL_API void blsDHKeyExchange(blsPublicKey *out, const blsSecretKey *sec, const blsPublicKey *pub); 386 | 387 | /* 388 | BLS Multi-Signatures With Public-Key Aggregation 389 | https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html 390 | H(pubVec)_i := SHA-256(pubVec[0], ..., pubVec[n-1], 4-byte little endian(i)) 391 | @note 392 | 1. this hash function will be modifed in the future 393 | 2. sigVec and pubVec are not const because they may be normalized (the value are not changed) 394 | */ 395 | // aggSig = sum sigVec[i] t_i where (t_1, ..., t_n) = H({pubVec}) 396 | BLS_DLL_API void blsMultiAggregateSignature(blsSignature *aggSig, blsSignature *sigVec, blsPublicKey *pubVec, mclSize n); 397 | // aggPub = sum pubVec[i] t_i where (t_1, ..., t_n) = H({pubVec}) 398 | BLS_DLL_API void blsMultiAggregatePublicKey(blsPublicKey *aggPub, blsPublicKey *pubVec, mclSize n); 399 | #endif // BLS_MINIMUM_API 400 | 401 | #ifdef __cplusplus 402 | } 403 | #endif 404 | -------------------------------------------------------------------------------- /bls/include/bls/bls384_256.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief C API of 384/256-bit 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #define MCLBN_FP_UNIT_SIZE 6 10 | #define MCLBN_FR_UNIT_SIZE 4 11 | #include 12 | 13 | -------------------------------------------------------------------------------- /bls/include/mcl/bn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief C interface of 256/384-bit optimal ate pairing over BN curves 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | /* 10 | the order of an elliptic curve over Fp is Fr 11 | */ 12 | #ifndef MCLBN_FP_UNIT_SIZE 13 | #error "define MCLBN_FP_UNIT_SIZE 4(, 6 or 8)" 14 | #endif 15 | #ifndef MCLBN_FR_UNIT_SIZE 16 | #define MCLBN_FR_UNIT_SIZE MCLBN_FP_UNIT_SIZE 17 | #endif 18 | #define MCLBN_COMPILED_TIME_VAR ((MCLBN_FR_UNIT_SIZE) * 10 + (MCLBN_FP_UNIT_SIZE)) 19 | 20 | #include // for uint64_t, uint8_t 21 | #include // for size_t 22 | 23 | 24 | #if defined(_WIN32) 25 | #ifdef MCLBN_DONT_EXPORT 26 | #define MCLBN_DLL_API 27 | #else 28 | #ifdef MCLBN_DLL_EXPORT 29 | #define MCLBN_DLL_API __declspec(dllexport) 30 | #else 31 | #define MCLBN_DLL_API //__declspec(dllimport) 32 | #endif 33 | #endif 34 | #if defined(_MSC_VER) && !defined(MCLBN_NO_AUTOLINK) 35 | #if MCLBN_FP_UNIT_SIZE == 4 36 | #pragma comment(lib, "mclbn256.lib") 37 | #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 4) 38 | #pragma comment(lib, "mclbn384_256.lib") 39 | #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 6) 40 | #pragma comment(lib, "mclbn384.lib") 41 | #elif MCLBN_FP_UNIT_SIZE == 8 42 | #pragma comment(lib, "mclbn512.lib") 43 | #endif 44 | #endif 45 | #elif defined(__EMSCRIPTEN__) && !defined(MCLBN_DONT_EXPORT) 46 | #define MCLBN_DLL_API __attribute__((used)) 47 | #elif defined(__wasm__) && !defined(MCLBN_DONT_EXPORT) 48 | #define MCLBN_DLL_API __attribute__((visibility("default"))) 49 | #else 50 | #define MCLBN_DLL_API 51 | #endif 52 | 53 | #ifdef __EMSCRIPTEN__ 54 | // avoid 64-bit integer 55 | #define mclSize unsigned int 56 | #define mclInt int 57 | #else 58 | // use #define for cgo 59 | #define mclSize size_t 60 | #define mclInt int64_t 61 | #endif 62 | 63 | #ifdef __cplusplus 64 | extern "C" { 65 | #endif 66 | 67 | #ifdef MCLBN_NOT_DEFINE_STRUCT 68 | 69 | typedef struct mclBnFr mclBnFr; 70 | typedef struct mclBnG1 mclBnG1; 71 | typedef struct mclBnG2 mclBnG2; 72 | typedef struct mclBnGT mclBnGT; 73 | typedef struct mclBnFp mclBnFp; 74 | typedef struct mclBnFp2 mclBnFp2; 75 | 76 | #else 77 | 78 | typedef struct { 79 | uint64_t d[MCLBN_FP_UNIT_SIZE]; 80 | } mclBnFp; 81 | 82 | /* 83 | x = d[0] + d[1] i where i^2 = -1 84 | */ 85 | typedef struct { 86 | mclBnFp d[2]; 87 | } mclBnFp2; 88 | 89 | /* 90 | G1 and G2 are isomorphism to Fr 91 | */ 92 | typedef struct { 93 | uint64_t d[MCLBN_FR_UNIT_SIZE]; 94 | } mclBnFr; 95 | 96 | /* 97 | G1 is defined over Fp 98 | */ 99 | typedef struct { 100 | mclBnFp x, y, z; 101 | } mclBnG1; 102 | 103 | typedef struct { 104 | mclBnFp2 x, y, z; 105 | } mclBnG2; 106 | 107 | typedef struct { 108 | mclBnFp d[12]; 109 | } mclBnGT; 110 | 111 | #endif 112 | 113 | #include 114 | 115 | #define MCLBN_IO_EC_AFFINE 0 116 | #define MCLBN_IO_EC_PROJ 1024 117 | #define MCLBN_IO_SERIALIZE_HEX_STR 2048 118 | 119 | // for backword compatibility 120 | enum { 121 | mclBn_CurveFp254BNb = 0, 122 | mclBn_CurveFp382_1 = 1, 123 | mclBn_CurveFp382_2 = 2, 124 | mclBn_CurveFp462 = 3, 125 | mclBn_CurveSNARK1 = 4, 126 | mclBls12_CurveFp381 = 5 127 | }; 128 | 129 | // return 0xABC which means A.BC 130 | MCLBN_DLL_API int mclBn_getVersion(void); 131 | /* 132 | init library 133 | @param curve [in] type of bn curve 134 | @param compiledTimeVar [in] specify MCLBN_COMPILED_TIME_VAR, 135 | which macro is used to make sure that the values 136 | are the same when the library is built and used 137 | @return 0 if success 138 | curve = BN254/BN_SNARK1 is allowed if maxUnitSize = 4 139 | curve = BN381_1/BN381_2/BLS12_381 are allowed if maxUnitSize = 6 140 | This parameter is used to detect a library compiled with different MCLBN_FP_UNIT_SIZE for safety. 141 | @note not threadsafe 142 | @note BN_init is used in libeay32 143 | */ 144 | MCLBN_DLL_API int mclBn_init(int curve, int compiledTimeVar); 145 | 146 | MCLBN_DLL_API int mclBn_getCurveType(void); 147 | 148 | /* 149 | pairing : G1 x G2 -> GT 150 | #G1 = #G2 = r 151 | G1 is a curve defined on Fp 152 | 153 | serialized size of elements 154 | |Fr| |Fp| 155 | BN254 32 32 156 | BN381 48 48 157 | BLS12_381 32 48 158 | BN462 58 58 159 | |G1| = |Fp| 160 | |G2| = |G1| * 2 161 | |GT| = |G1| * 12 162 | */ 163 | /* 164 | return the num of Unit(=uint64_t) to store Fr 165 | */ 166 | MCLBN_DLL_API int mclBn_getOpUnitSize(void); 167 | 168 | /* 169 | return bytes for serialized G1(=size of Fp) + adj 170 | adj = 1 if p is full bit else 0 171 | */ 172 | MCLBN_DLL_API int mclBn_getG1ByteSize(void); 173 | /* 174 | return bytes for serialized G2(=size of Fp2) + adj 175 | adj = 1 if p is full bit else 0 176 | */ 177 | MCLBN_DLL_API int mclBn_getG2ByteSize(void); 178 | /* 179 | return bytes for serialized Fr 180 | */ 181 | MCLBN_DLL_API int mclBn_getFrByteSize(void); 182 | /* 183 | return bytes for serialized Fp 184 | */ 185 | MCLBN_DLL_API int mclBn_getFpByteSize(void); 186 | 187 | /* 188 | return decimal string of the order of the curve(=the characteristic of Fr) 189 | return str(buf) if success 190 | */ 191 | MCLBN_DLL_API mclSize mclBn_getCurveOrder(char *buf, mclSize maxBufSize); 192 | 193 | /* 194 | return decimal string of the characteristic of Fp 195 | return str(buf) if success 196 | */ 197 | MCLBN_DLL_API mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize); 198 | 199 | /* 200 | set ETH serialization mode for BLS12-381 201 | @param enable [in] 1:enable, 0:disable 202 | @note ignore the flag if curve is not BLS12-381 203 | */ 204 | MCLBN_DLL_API void mclBn_setETHserialization(int enable); 205 | 206 | // return 1 if ETH serialization mode else 0 207 | MCLBN_DLL_API int mclBn_getETHserialization(void); 208 | 209 | /* 210 | set map-to-function to mode (only support MCL_MAP_TO_MODE_HASH_TO_CURVE_07) 211 | return 0 if success else -1 212 | */ 213 | MCLBN_DLL_API int mclBn_setMapToMode(int mode); 214 | 215 | //////////////////////////////////////////////// 216 | /* 217 | deserialize 218 | return read size if success else 0 219 | */ 220 | MCLBN_DLL_API mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize); 221 | MCLBN_DLL_API mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize); 222 | MCLBN_DLL_API mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize); 223 | MCLBN_DLL_API mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize); 224 | MCLBN_DLL_API mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize); 225 | MCLBN_DLL_API mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize); 226 | 227 | /* 228 | serialize 229 | return written byte if sucess else 0 230 | */ 231 | MCLBN_DLL_API mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mclBnFr *x); 232 | MCLBN_DLL_API mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x); 233 | MCLBN_DLL_API mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x); 234 | MCLBN_DLL_API mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x); 235 | MCLBN_DLL_API mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x); 236 | MCLBN_DLL_API mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x); 237 | 238 | /* 239 | set string 240 | ioMode 241 | 10 : decimal number 242 | 16 : hexadecimal number 243 | MCLBN_IO_SERIALIZE_HEX_STR : hex string of serialized data 244 | return 0 if success else -1 245 | */ 246 | MCLBN_DLL_API int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode); 247 | MCLBN_DLL_API int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode); 248 | MCLBN_DLL_API int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode); 249 | MCLBN_DLL_API int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode); 250 | MCLBN_DLL_API int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode); 251 | 252 | /* 253 | buf is terminated by '\0' 254 | return strlen(buf) if sucess else 0 255 | */ 256 | MCLBN_DLL_API mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnFr *x, int ioMode); 257 | MCLBN_DLL_API mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode); 258 | MCLBN_DLL_API mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode); 259 | MCLBN_DLL_API mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode); 260 | MCLBN_DLL_API mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode); 261 | 262 | // set zero 263 | MCLBN_DLL_API void mclBnFr_clear(mclBnFr *x); 264 | MCLBN_DLL_API void mclBnFp_clear(mclBnFp *x); 265 | MCLBN_DLL_API void mclBnFp2_clear(mclBnFp2 *x); 266 | 267 | // set x to y 268 | MCLBN_DLL_API void mclBnFr_setInt(mclBnFr *y, mclInt x); 269 | MCLBN_DLL_API void mclBnFr_setInt32(mclBnFr *y, int x); 270 | MCLBN_DLL_API void mclBnFp_setInt(mclBnFp *y, mclInt x); 271 | MCLBN_DLL_API void mclBnFp_setInt32(mclBnFp *y, int x); 272 | 273 | // x = buf & (1 << bitLen(r)) - 1 274 | // if (x >= r) x &= (1 << (bitLen(r) - 1)) - 1 275 | // always return 0 276 | MCLBN_DLL_API int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize); 277 | MCLBN_DLL_API int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize); 278 | 279 | /* 280 | write a value as little endian 281 | return written size if success else 0 282 | @note buf[0] = 0 and return 1 if the value is zero 283 | */ 284 | MCLBN_DLL_API mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x); 285 | MCLBN_DLL_API mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x); 286 | 287 | // set (buf mod r) to x 288 | // return 0 if bufSize <= (byte size of Fr * 2) else -1 289 | MCLBN_DLL_API int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize); 290 | MCLBN_DLL_API int mclBnFr_setBigEndianMod(mclBnFr *x, const void *buf, mclSize bufSize); 291 | // set (buf mod p) to x 292 | // return 0 if bufSize <= (byte size of Fp * 2) else -1 293 | MCLBN_DLL_API int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize); 294 | MCLBN_DLL_API int mclBnFp_setBigEndianMod(mclBnFp *x, const void *buf, mclSize bufSize); 295 | 296 | // return 1 if true and 0 otherwise 297 | MCLBN_DLL_API int mclBnFr_isValid(const mclBnFr *x); 298 | MCLBN_DLL_API int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y); 299 | MCLBN_DLL_API int mclBnFr_isZero(const mclBnFr *x); 300 | MCLBN_DLL_API int mclBnFr_isOne(const mclBnFr *x); 301 | MCLBN_DLL_API int mclBnFr_isOdd(const mclBnFr *x); 302 | // return 1 if half <= x < r, where half = (r + 1) / 2 else 0 303 | MCLBN_DLL_API int mclBnFr_isNegative(const mclBnFr *x); 304 | // compare x and y as unsigned 305 | // return x < y ? -1 : x == y ? 0 : 1; 306 | // @note two Montgomery conversions may be required 307 | MCLBN_DLL_API int mclBnFr_cmp(const mclBnFr *x, const mclBnFr *y); 308 | 309 | MCLBN_DLL_API int mclBnFp_isValid(const mclBnFp *x); 310 | MCLBN_DLL_API int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y); 311 | MCLBN_DLL_API int mclBnFp_isZero(const mclBnFp *x); 312 | MCLBN_DLL_API int mclBnFp_isOne(const mclBnFp *x); 313 | MCLBN_DLL_API int mclBnFp_isOdd(const mclBnFp *x); 314 | // return 1 if half <= x < p, where half = (p + 1) / 2 else 0 315 | MCLBN_DLL_API int mclBnFp_isNegative(const mclBnFp *x); 316 | // compare x and y as unsigned 317 | // return x < y ? -1 : x == y ? 0 : 1; 318 | // @note two Montgomery conversions may be required 319 | MCLBN_DLL_API int mclBnFp_cmp(const mclBnFp *x, const mclBnFp *y); 320 | 321 | MCLBN_DLL_API int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y); 322 | MCLBN_DLL_API int mclBnFp2_isZero(const mclBnFp2 *x); 323 | MCLBN_DLL_API int mclBnFp2_isOne(const mclBnFp2 *x); 324 | 325 | 326 | #ifndef MCL_DONT_USE_CSRPNG 327 | // return 0 if success 328 | MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x); 329 | MCLBN_DLL_API int mclBnFp_setByCSPRNG(mclBnFp *x); 330 | 331 | /* 332 | set user-defined random function for setByCSPRNG 333 | @param self [in] user-defined pointer 334 | @param readFunc [in] user-defined function, 335 | which writes random bufSize bytes to buf and returns bufSize if success else returns 0 336 | @note if self == 0 and readFunc == 0 then set default random function 337 | @note not threadsafe 338 | */ 339 | MCLBN_DLL_API void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)); 340 | #endif 341 | 342 | // hash(s) and set x 343 | // return 0 if success 344 | MCLBN_DLL_API int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize); 345 | MCLBN_DLL_API int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize); 346 | 347 | // map x to y 348 | // return 0 if success else -1 349 | MCLBN_DLL_API int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x); 350 | MCLBN_DLL_API int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x); 351 | 352 | MCLBN_DLL_API void mclBnFr_neg(mclBnFr *y, const mclBnFr *x); 353 | MCLBN_DLL_API void mclBnFr_inv(mclBnFr *y, const mclBnFr *x); 354 | MCLBN_DLL_API void mclBnFr_sqr(mclBnFr *y, const mclBnFr *x); 355 | MCLBN_DLL_API void mclBnFr_add(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 356 | MCLBN_DLL_API void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 357 | MCLBN_DLL_API void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 358 | MCLBN_DLL_API void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 359 | 360 | MCLBN_DLL_API void mclBnFp_neg(mclBnFp *y, const mclBnFp *x); 361 | MCLBN_DLL_API void mclBnFp_inv(mclBnFp *y, const mclBnFp *x); 362 | MCLBN_DLL_API void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x); 363 | MCLBN_DLL_API void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y); 364 | MCLBN_DLL_API void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y); 365 | MCLBN_DLL_API void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y); 366 | MCLBN_DLL_API void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y); 367 | 368 | MCLBN_DLL_API void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x); 369 | MCLBN_DLL_API void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x); 370 | MCLBN_DLL_API void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x); 371 | MCLBN_DLL_API void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y); 372 | MCLBN_DLL_API void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y); 373 | MCLBN_DLL_API void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y); 374 | MCLBN_DLL_API void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y); 375 | 376 | // y is one of square root of x 377 | // return 0 if success else -1 378 | MCLBN_DLL_API int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x); 379 | MCLBN_DLL_API int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x); 380 | MCLBN_DLL_API int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x); 381 | 382 | //////////////////////////////////////////////// 383 | // set zero 384 | MCLBN_DLL_API void mclBnG1_clear(mclBnG1 *x); 385 | 386 | 387 | // return 1 if true and 0 otherwise 388 | MCLBN_DLL_API int mclBnG1_isValid(const mclBnG1 *x); 389 | MCLBN_DLL_API int mclBnG1_isEqual(const mclBnG1 *x, const mclBnG1 *y); 390 | MCLBN_DLL_API int mclBnG1_isZero(const mclBnG1 *x); 391 | /* 392 | return 1 if x has a correct order 393 | x is valid point of G1 if and only if 394 | mclBnG1_isValid() is true, which contains mclBnG1_isValidOrder() if mclBn_verifyOrderG1(true) 395 | mclBnG1_isValid() && mclBnG1_isValidOrder() is true if mclBn_verifyOrderG1(false) 396 | */ 397 | MCLBN_DLL_API int mclBnG1_isValidOrder(const mclBnG1 *x); 398 | 399 | MCLBN_DLL_API int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, mclSize bufSize); 400 | // user-defined dst 401 | MCLBN_DLL_API int mclBnG1_hashAndMapToWithDst(mclBnG1 *x, const void *buf, mclSize bufSize, const char *dst, mclSize dstSize); 402 | // set default dst 403 | MCLBN_DLL_API int mclBnG1_setDst(const char *dst, mclSize dstSize); 404 | 405 | 406 | MCLBN_DLL_API void mclBnG1_neg(mclBnG1 *y, const mclBnG1 *x); 407 | MCLBN_DLL_API void mclBnG1_dbl(mclBnG1 *y, const mclBnG1 *x); 408 | MCLBN_DLL_API void mclBnG1_normalize(mclBnG1 *y, const mclBnG1 *x); 409 | MCLBN_DLL_API void mclBnG1_add(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y); 410 | MCLBN_DLL_API void mclBnG1_sub(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y); 411 | MCLBN_DLL_API void mclBnG1_mul(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y); 412 | 413 | /* 414 | constant time mul 415 | */ 416 | MCLBN_DLL_API void mclBnG1_mulCT(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y); 417 | 418 | //////////////////////////////////////////////// 419 | // set zero 420 | MCLBN_DLL_API void mclBnG2_clear(mclBnG2 *x); 421 | 422 | // return 1 if true and 0 otherwise 423 | MCLBN_DLL_API int mclBnG2_isValid(const mclBnG2 *x); 424 | MCLBN_DLL_API int mclBnG2_isEqual(const mclBnG2 *x, const mclBnG2 *y); 425 | MCLBN_DLL_API int mclBnG2_isZero(const mclBnG2 *x); 426 | // return 1 if x has a correct order 427 | MCLBN_DLL_API int mclBnG2_isValidOrder(const mclBnG2 *x); 428 | 429 | MCLBN_DLL_API int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, mclSize bufSize); 430 | // user-defined dst 431 | MCLBN_DLL_API int mclBnG2_hashAndMapToWithDst(mclBnG2 *x, const void *buf, mclSize bufSize, const char *dst, mclSize dstSize); 432 | // set default dst 433 | MCLBN_DLL_API int mclBnG2_setDst(const char *dst, mclSize dstSize); 434 | 435 | // return written size if sucess else 0 436 | 437 | MCLBN_DLL_API void mclBnG2_neg(mclBnG2 *y, const mclBnG2 *x); 438 | MCLBN_DLL_API void mclBnG2_dbl(mclBnG2 *y, const mclBnG2 *x); 439 | MCLBN_DLL_API void mclBnG2_normalize(mclBnG2 *y, const mclBnG2 *x); 440 | MCLBN_DLL_API void mclBnG2_add(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y); 441 | MCLBN_DLL_API void mclBnG2_sub(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y); 442 | MCLBN_DLL_API void mclBnG2_mul(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y); 443 | /* 444 | constant time mul 445 | */ 446 | MCLBN_DLL_API void mclBnG2_mulCT(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y); 447 | 448 | //////////////////////////////////////////////// 449 | // set zero 450 | MCLBN_DLL_API void mclBnGT_clear(mclBnGT *x); 451 | // set x to y 452 | MCLBN_DLL_API void mclBnGT_setInt(mclBnGT *y, mclInt x); 453 | MCLBN_DLL_API void mclBnGT_setInt32(mclBnGT *y, int x); 454 | 455 | // return 1 if true and 0 otherwise 456 | MCLBN_DLL_API int mclBnGT_isEqual(const mclBnGT *x, const mclBnGT *y); 457 | MCLBN_DLL_API int mclBnGT_isZero(const mclBnGT *x); 458 | MCLBN_DLL_API int mclBnGT_isOne(const mclBnGT *x); 459 | 460 | MCLBN_DLL_API void mclBnGT_neg(mclBnGT *y, const mclBnGT *x); 461 | MCLBN_DLL_API void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x); 462 | MCLBN_DLL_API void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 463 | MCLBN_DLL_API void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 464 | MCLBN_DLL_API void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 465 | MCLBN_DLL_API void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 466 | 467 | // y = conjugate of x in Fp12, which is equal to the inverse of x if |x|^r = 1 468 | MCLBN_DLL_API void mclBnGT_inv(mclBnGT *y, const mclBnGT *x); 469 | // use invGeneric when x in Fp12 is not in GT 470 | MCLBN_DLL_API void mclBnGT_invGeneric(mclBnGT *y, const mclBnGT *x); 471 | 472 | /* 473 | pow for all elements of Fp12 474 | */ 475 | MCLBN_DLL_API void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y); 476 | /* 477 | pow for only {x|x^r = 1} in GT by GLV method 478 | the value generated by pairing satisfies the condition 479 | */ 480 | MCLBN_DLL_API void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y); 481 | 482 | // z = sum_{i=0}^{n-1} x[i] y[i] 483 | // x[] may be normalized (the values are not changed) when computing z 484 | MCLBN_DLL_API void mclBnG1_mulVec(mclBnG1 *z, mclBnG1 *x, const mclBnFr *y, mclSize n); 485 | MCLBN_DLL_API void mclBnG2_mulVec(mclBnG2 *z, mclBnG2 *x, const mclBnFr *y, mclSize n); 486 | MCLBN_DLL_API void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n); 487 | 488 | MCLBN_DLL_API void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y); 489 | MCLBN_DLL_API void mclBn_finalExp(mclBnGT *y, const mclBnGT *x); 490 | MCLBN_DLL_API void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y); 491 | // z = prod_{i=0}^{n-1} millerLoop(x[i], y[i]) 492 | MCLBN_DLL_API void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n); 493 | // multi thread version of millerLoopVec/mclBnG1_mulVec/mclBnG2_mulVec (enabled if the library built with MCL_USE_OMP=1) 494 | // the num of thread is automatically detected if cpuN = 0 495 | // x[] may be normalized (the values are not changed) when computing z 496 | MCLBN_DLL_API void mclBn_millerLoopVecMT(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n, mclSize cpuN); 497 | MCLBN_DLL_API void mclBnG1_mulVecMT(mclBnG1 *z, mclBnG1 *x, const mclBnFr *y, mclSize n, mclSize cpuN); 498 | MCLBN_DLL_API void mclBnG2_mulVecMT(mclBnG2 *z, mclBnG2 *x, const mclBnFr *y, mclSize n, mclSize cpuN); 499 | 500 | // return precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t) 501 | MCLBN_DLL_API int mclBn_getUint64NumToPrecompute(void); 502 | 503 | // allocate Qbuf[MCLBN_getUint64NumToPrecompute()] before calling this 504 | MCLBN_DLL_API void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q); 505 | 506 | MCLBN_DLL_API void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf); 507 | MCLBN_DLL_API void mclBn_precomputedMillerLoop2(mclBnGT *f, const mclBnG1 *P1, const uint64_t *Q1buf, const mclBnG1 *P2, const uint64_t *Q2buf); 508 | MCLBN_DLL_API void mclBn_precomputedMillerLoop2mixed(mclBnGT *f, const mclBnG1 *P1, const mclBnG2 *Q1, const mclBnG1 *P2, const uint64_t *Q2buf); 509 | 510 | /* 511 | Lagrange interpolation 512 | recover out = y(0) by { (xVec[i], yVec[i]) } 513 | return 0 if success else -1 514 | @note *out = yVec[0] if k = 1 515 | @note k >= 2, xVec[i] != 0, xVec[i] != xVec[j] for i != j 516 | */ 517 | MCLBN_DLL_API int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k); 518 | MCLBN_DLL_API int mclBn_G1LagrangeInterpolation(mclBnG1 *out, const mclBnFr *xVec, const mclBnG1 *yVec, mclSize k); 519 | MCLBN_DLL_API int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVec, const mclBnG2 *yVec, mclSize k); 520 | 521 | /* 522 | evaluate polynomial 523 | out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1) 524 | return 0 if success else -1 525 | @note cSize >= 1 526 | */ 527 | MCLBN_DLL_API int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x); 528 | MCLBN_DLL_API int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x); 529 | MCLBN_DLL_API int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, const mclBnFr *x); 530 | 531 | /* 532 | verify whether a point of an elliptic curve has order r 533 | This api affetcs setStr(), deserialize() for G2 on BN or G1/G2 on BLS12 534 | @param doVerify [in] does not verify if zero(default 1) 535 | */ 536 | MCLBN_DLL_API void mclBn_verifyOrderG1(int doVerify); 537 | MCLBN_DLL_API void mclBn_verifyOrderG2(int doVerify); 538 | 539 | /* 540 | EXPERIMENTAL 541 | only for curve = MCL_SECP* or MCL_NIST* 542 | return standard base point of the current elliptic curve 543 | */ 544 | MCLBN_DLL_API int mclBnG1_getBasePoint(mclBnG1 *x); 545 | 546 | #ifdef __cplusplus 547 | } 548 | #endif 549 | -------------------------------------------------------------------------------- /bls/include/mcl/bn_c384_256.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief C API of 384/256-bit optimal ate pairing over BN curves 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #define MCLBN_FP_UNIT_SIZE 6 10 | #define MCLBN_FR_UNIT_SIZE 4 11 | #include 12 | 13 | -------------------------------------------------------------------------------- /bls/include/mcl/curve_type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief curve type 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | 10 | enum { 11 | MCL_BN254 = 0, 12 | MCL_BN381_1 = 1, 13 | MCL_BN381_2 = 2, 14 | MCL_BN462 = 3, 15 | MCL_BN_SNARK1 = 4, 16 | MCL_BLS12_381 = 5, 17 | MCL_BN160 = 6, 18 | MCL_BLS12_461 = 7, 19 | MCL_BLS12_377 = 8, 20 | MCL_BN_P256 = 9, 21 | 22 | /* 23 | for only G1 24 | the size of curve must be <= MCLBN_FP_UNIT_SIZE 25 | */ 26 | MCL_EC_BEGIN = 100, 27 | MCL_SECP192K1 = MCL_EC_BEGIN, 28 | MCL_SECP224K1 = 101, 29 | MCL_SECP256K1 = 102, 30 | MCL_SECP384R1 = 103, 31 | MCL_SECP521R1 = 104, 32 | MCL_NIST_P192 = 105, 33 | MCL_NIST_P224 = 106, 34 | MCL_NIST_P256 = 107, 35 | MCL_SECP160K1 = 108, 36 | MCL_P160_1 = 109, 37 | MCL_EC_END = MCL_P160_1 + 1, 38 | MCL_NIST_P384 = MCL_SECP384R1, 39 | MCL_NIST_P521 = MCL_SECP521R1 40 | }; 41 | 42 | /* 43 | remark : if irtf-cfrg-hash-to-curve is compeletely fixed, then 44 | MCL_MAP_TO_MODE_WB19, MCL_MAP_TO_MODE_HASH_TO_CURVE_0? will be removed and 45 | only MCL_MAP_TO_MODE_HASH_TO_CURVE will be available. 46 | */ 47 | enum { 48 | MCL_MAP_TO_MODE_ORIGINAL, // see MapTo::calcBN 49 | MCL_MAP_TO_MODE_TRY_AND_INC, // try-and-incremental-x 50 | MCL_MAP_TO_MODE_ETH2, // (deprecated) old eth2.0 spec 51 | MCL_MAP_TO_MODE_WB19, // (deprecated) used in new eth2.0 spec 52 | MCL_MAP_TO_MODE_HASH_TO_CURVE_05 = MCL_MAP_TO_MODE_WB19, // (deprecated) draft-irtf-cfrg-hash-to-curve-05 53 | MCL_MAP_TO_MODE_HASH_TO_CURVE_06, // (deprecated) draft-irtf-cfrg-hash-to-curve-06 54 | MCL_MAP_TO_MODE_HASH_TO_CURVE_07 = 5, /* don't change this value! */ // draft-irtf-cfrg-hash-to-curve-07 55 | MCL_MAP_TO_MODE_HASH_TO_CURVE = MCL_MAP_TO_MODE_HASH_TO_CURVE_07, // the latset version 56 | MCL_MAP_TO_MODE_ETH2_LEGACY // backwards compatible version of MCL_MAP_TO_MODE_ETH2 with commit 730c50d4eaff1e0d685a92ac8c896e873749471b 57 | }; 58 | 59 | #ifdef __cplusplus 60 | 61 | #include 62 | #include 63 | 64 | namespace mcl { 65 | 66 | struct CurveParam { 67 | /* 68 | y^2 = x^3 + b 69 | i^2 = -1 70 | xi = xi_a + i 71 | v^3 = xi 72 | w^2 = v 73 | */ 74 | const char *z; 75 | int b; // y^2 = x^3 + b 76 | int xi_a; // xi = xi_a + i 77 | /* 78 | BN254, BN381, BLS12_377 : Dtype 79 | BLS12-381, BN_P256 : Mtype 80 | */ 81 | bool isMtype; 82 | int curveType; // same in curve_type.h 83 | bool operator==(const CurveParam& rhs) const 84 | { 85 | return strcmp(z, rhs.z) == 0 && b == rhs.b && xi_a == rhs.xi_a && isMtype == rhs.isMtype; 86 | } 87 | bool operator!=(const CurveParam& rhs) const { return !operator==(rhs); } 88 | }; 89 | 90 | const CurveParam BN254 = { "-0x4080000000000001", 2, 1, false, MCL_BN254 }; // -(2^62 + 2^55 + 1) 91 | const CurveParam BN_P256 = { "-0x6882f5c030b0a801", 3, 1, true, MCL_BN_P256 }; // BN P256 defined in TCG Algorithm Registry Family "2.0", Revision 1.32 92 | // provisional(experimental) param with maxBitSize = 384 93 | const CurveParam BN381_1 = { "-0x400011000000000000000001", 2, 1, false, MCL_BN381_1 }; // -(2^94 + 2^76 + 2^72 + 1) // A Family of Implementation-Friendly BN Elliptic Curves 94 | const CurveParam BN381_2 = { "-0x400040090001000000000001", 2, 1, false, MCL_BN381_2 }; // -(2^94 + 2^78 + 2^67 + 2^64 + 2^48 + 1) // used in relic-toolkit 95 | const CurveParam BN462 = { "0x4001fffffffffffffffffffffbfff", 5, 2, false, MCL_BN462 }; // 2^114 + 2^101 - 2^14 - 1 // https://eprint.iacr.org/2017/334 96 | const CurveParam BN_SNARK1 = { "4965661367192848881", 3, 9, false, MCL_BN_SNARK1 }; 97 | const CurveParam BLS12_381 = { "-0xd201000000010000", 4, 1, true, MCL_BLS12_381 }; 98 | const CurveParam BN160 = { "0x4000000031", 3, 4, false, MCL_BN160 }; 99 | const CurveParam BLS12_461 = { "-0x1ffffffbfffe00000000", 4, 1, true, MCL_BLS12_461 }; 100 | // QQQ BLS12_377 is under construction 101 | const CurveParam BLS12_377 = { "0x8508c00000000001", 1, 0, false, MCL_BLS12_377 }; // not supported yet 102 | 103 | #ifdef __clang__ 104 | #pragma GCC diagnostic push 105 | #pragma GCC diagnostic ignored "-Wreturn-type-c-linkage" 106 | #endif 107 | inline const CurveParam* getCurveParam(int type) 108 | { 109 | switch (type) { 110 | case MCL_BN254: return &mcl::BN254; 111 | case MCL_BN_P256: return &mcl::BN_P256; 112 | case MCL_BN381_1: return &mcl::BN381_1; 113 | case MCL_BN381_2: return &mcl::BN381_2; 114 | case MCL_BN462: return &mcl::BN462; 115 | case MCL_BN_SNARK1: return &mcl::BN_SNARK1; 116 | case MCL_BLS12_381: return &mcl::BLS12_381; 117 | case MCL_BN160: return &mcl::BN160; 118 | default: 119 | return 0; 120 | } 121 | } 122 | #ifdef __clang__ 123 | #pragma GCC diagnostic pop 124 | #endif 125 | 126 | } // mcl 127 | #endif 128 | -------------------------------------------------------------------------------- /bls/link.go: -------------------------------------------------------------------------------- 1 | //go:build !ios 2 | // +build !ios 3 | 4 | package bls 5 | 6 | /* 7 | #cgo LDFLAGS:-lbls384_256 -lm 8 | #cgo amd64 LDFLAGS:-lstdc++ 9 | #cgo android,arm64 LDFLAGS:-L${SRCDIR}/lib/android/arm64-v8a 10 | #cgo android,arm LDFLAGS:-L${SRCDIR}/lib/android/armeabi-v7a 11 | #cgo android,amd64 LDFLAGS:-L${SRCDIR}/lib/android/x86_64 12 | #cgo linux,amd64 LDFLAGS:-L${SRCDIR}/lib/linux/amd64 13 | #cgo linux,arm64 LDFLAGS:-L${SRCDIR}/lib/linux/arm64 14 | #cgo linux,mipsle LDFLAGS:-L${SRCDIR}/lib/linux/mipsel 15 | #cgo linux,arm LDFLAGS:-L${SRCDIR}/lib/linux/arm 16 | #cgo linux,s390x LDFLAGS:-L${SRCDIR}/lib/linux/s390x 17 | #cgo linux,riscv64 LDFLAGS:-L${SRCDIR}/lib/linux/riscv64 18 | #cgo darwin,amd64 LDFLAGS:-L${SRCDIR}/lib/darwin/amd64 19 | #cgo darwin,arm64 LDFLAGS:-L${SRCDIR}/lib/darwin/arm64 20 | #cgo windows,amd64 LDFLAGS:-L${SRCDIR}/lib/windows/amd64 21 | #cgo openbsd,amd64 LDFLAGS:-L${SRCDIR}/lib/openbsd/amd64 22 | #cgo freebsd,amd64 LDFLAGS:-L${SRCDIR}/lib/freebsd/amd64 23 | */ 24 | import "C" 25 | -------------------------------------------------------------------------------- /bls/link_ios.go: -------------------------------------------------------------------------------- 1 | //go:build ios && !iossimulator 2 | // +build ios,!iossimulator 3 | 4 | package bls 5 | 6 | /* 7 | #cgo LDFLAGS:-lbls384_256 -lstdc++ -lm 8 | #cgo ios LDFLAGS:-L${SRCDIR}/lib/ios 9 | */ 10 | import "C" 11 | -------------------------------------------------------------------------------- /bls/link_iossimulator.go: -------------------------------------------------------------------------------- 1 | //go:build iossimulator 2 | // +build iossimulator 3 | 4 | package bls 5 | 6 | /* 7 | #cgo LDFLAGS:-lbls384_256 -lstdc++ -lm 8 | #cgo ios LDFLAGS:-L${SRCDIR}/lib/iossimulator 9 | */ 10 | import "C" 11 | -------------------------------------------------------------------------------- /bls/mcl.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | /* 4 | #cgo CFLAGS:-I./include 5 | #include 6 | */ 7 | import "C" 8 | import "fmt" 9 | import "unsafe" 10 | 11 | // CurveFp254BNb -- 254 bit curve 12 | const CurveFp254BNb = C.mclBn_CurveFp254BNb 13 | 14 | // CurveFp382_1 -- 382 bit curve 1 15 | const CurveFp382_1 = C.mclBn_CurveFp382_1 16 | 17 | // CurveFp382_2 -- 382 bit curve 2 18 | const CurveFp382_2 = C.mclBn_CurveFp382_2 19 | 20 | // BLS12_381 -- 21 | const BLS12_381 = C.MCL_BLS12_381 22 | 23 | // IoSerializeHexStr -- 24 | const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR 25 | 26 | // IO_EC_AFFINE -- 27 | const IO_EC_AFFINE = C.MCLBN_IO_EC_AFFINE 28 | 29 | // IO_EC_PROJ -- 30 | const IO_EC_PROJ = C.MCLBN_IO_EC_PROJ 31 | 32 | // IRTF -- for SetMapToMode 33 | const IRTF = 5 /* MCL_MAP_TO_MODE_HASH_TO_CURVE_07 */ 34 | 35 | // GetFrUnitSize -- 36 | func GetFrUnitSize() int { 37 | return int(C.MCLBN_FR_UNIT_SIZE) 38 | } 39 | 40 | // GetFpUnitSize -- 41 | // same as GetMaxOpUnitSize() 42 | func GetFpUnitSize() int { 43 | return int(C.MCLBN_FP_UNIT_SIZE) 44 | } 45 | 46 | // GetMaxOpUnitSize -- 47 | func GetMaxOpUnitSize() int { 48 | return int(C.MCLBN_FP_UNIT_SIZE) 49 | } 50 | 51 | // GetOpUnitSize -- 52 | // the length of Fr is GetOpUnitSize() * 8 bytes 53 | func GetOpUnitSize() int { 54 | return int(C.mclBn_getOpUnitSize()) 55 | } 56 | 57 | // GetFrByteSize -- the serialized size of Fr 58 | func GetFrByteSize() int { 59 | return int(C.mclBn_getFrByteSize()) 60 | } 61 | 62 | // GetFpByteSize -- the serialized size of Fp 63 | func GetFpByteSize() int { 64 | return int(C.mclBn_getFpByteSize()) 65 | } 66 | 67 | // GetG1ByteSize -- the serialized size of G1 68 | func GetG1ByteSize() int { 69 | return int(C.mclBn_getG1ByteSize()) 70 | } 71 | 72 | // GetG2ByteSize -- the serialized size of G2 73 | func GetG2ByteSize() int { 74 | return int(C.mclBn_getG2ByteSize()) 75 | } 76 | 77 | // allow zero length byte 78 | func getPointer(msg []byte) unsafe.Pointer { 79 | if len(msg) == 0 { 80 | return nil 81 | } 82 | return unsafe.Pointer(&msg[0]) 83 | } 84 | 85 | // GetCurveOrder -- 86 | // return the order of G1 87 | func GetCurveOrder() string { 88 | buf := make([]byte, 1024) 89 | // #nosec 90 | n := C.mclBn_getCurveOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) 91 | if n == 0 { 92 | panic("implementation err. size of buf is small") 93 | } 94 | return string(buf[:n]) 95 | } 96 | 97 | // GetFieldOrder -- 98 | // return the characteristic of the field where a curve is defined 99 | func GetFieldOrder() string { 100 | buf := make([]byte, 1024) 101 | // #nosec 102 | n := C.mclBn_getFieldOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) 103 | if n == 0 { 104 | panic("implementation err. size of buf is small") 105 | } 106 | return string(buf[:n]) 107 | } 108 | 109 | func bool2Cint(b bool) C.int { 110 | if b { 111 | return 1 112 | } else { 113 | return 0 114 | } 115 | } 116 | 117 | // VerifyOrderG1 -- verify order if SetString/Deserialize are called 118 | func VerifyOrderG1(doVerify bool) { 119 | // #nosec 120 | C.mclBn_verifyOrderG1(bool2Cint(doVerify)) 121 | } 122 | 123 | // VerifyOrderG2 -- verify order if SetString/Deserialize are called 124 | func VerifyOrderG2(doVerify bool) { 125 | // #nosec 126 | C.mclBn_verifyOrderG2(bool2Cint(doVerify)) 127 | } 128 | 129 | // SetETHserialization -- 130 | func SetETHserialization(enable bool) { 131 | // #nosec 132 | C.mclBn_setETHserialization(bool2Cint(enable)) 133 | } 134 | 135 | // SetMapToMode -- 136 | func SetMapToMode(mode int) error { 137 | // #nosec 138 | err := C.mclBn_setMapToMode((C.int)(mode)) 139 | if err != 0 { 140 | return fmt.Errorf("SetMapToMode mode=%d\n", mode) 141 | } 142 | return nil 143 | } 144 | 145 | // SetDstG1 -- 146 | func SetDstG1(s string) error { 147 | // #nosec 148 | err := C.mclBnG1_setDst((*C.char)(getPointer([]byte(s))), C.size_t(len(s))) 149 | if err != 0 { 150 | return fmt.Errorf("err mclBnG1_setDst") 151 | } 152 | return nil 153 | } 154 | 155 | // SetDstG2 -- 156 | func SetDstG2(s string) error { 157 | // #nosec 158 | err := C.mclBnG2_setDst((*C.char)(getPointer([]byte(s))), C.size_t(len(s))) 159 | if err != 0 { 160 | return fmt.Errorf("err mclBnG2_setDst") 161 | } 162 | return nil 163 | } 164 | 165 | // Fr -- 166 | type Fr struct { 167 | v C.mclBnFr 168 | } 169 | 170 | // getPointer -- 171 | func (x *Fr) getPointer() (p *C.mclBnFr) { 172 | // #nosec 173 | return (*C.mclBnFr)(unsafe.Pointer(x)) 174 | } 175 | 176 | // Clear -- 177 | func (x *Fr) Clear() { 178 | // #nosec 179 | C.mclBnFr_clear(x.getPointer()) 180 | } 181 | 182 | // SetInt64 -- 183 | func (x *Fr) SetInt64(v int64) { 184 | // #nosec 185 | C.mclBnFr_setInt(x.getPointer(), C.int64_t(v)) 186 | } 187 | 188 | // SetString -- 189 | func (x *Fr) SetString(s string, base int) error { 190 | buf := []byte(s) 191 | // #nosec 192 | err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base)) 193 | if err != 0 { 194 | return fmt.Errorf("err mclBnFr_setStr %x", err) 195 | } 196 | return nil 197 | } 198 | 199 | // Deserialize -- 200 | func (x *Fr) Deserialize(buf []byte) error { 201 | // #nosec 202 | n := C.mclBnFr_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 203 | if n == 0 || int(n) != len(buf) { 204 | return fmt.Errorf("err mclBnFr_deserialize %x", buf) 205 | } 206 | return nil 207 | } 208 | 209 | // SetLittleEndian -- 210 | func (x *Fr) SetLittleEndian(buf []byte) error { 211 | // #nosec 212 | err := C.mclBnFr_setLittleEndian(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 213 | if err != 0 { 214 | return fmt.Errorf("err mclBnFr_setLittleEndian %x", err) 215 | } 216 | return nil 217 | } 218 | 219 | // SetLittleEndianMod -- 220 | func (x *Fr) SetLittleEndianMod(buf []byte) error { 221 | // #nosec 222 | err := C.mclBnFr_setLittleEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 223 | if err != 0 { 224 | return fmt.Errorf("err mclBnFr_setLittleEndianMod %x", err) 225 | } 226 | return nil 227 | } 228 | 229 | // SetBigEndianMod -- 230 | func (x *Fr) SetBigEndianMod(buf []byte) error { 231 | // #nosec 232 | err := C.mclBnFr_setBigEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 233 | if err != 0 { 234 | return fmt.Errorf("err mclBnFr_setBigEndianMod %x", err) 235 | } 236 | return nil 237 | } 238 | 239 | // IsEqual -- 240 | func (x *Fr) IsEqual(rhs *Fr) bool { 241 | return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1 242 | } 243 | 244 | // IsZero -- 245 | func (x *Fr) IsZero() bool { 246 | return C.mclBnFr_isZero(x.getPointer()) == 1 247 | } 248 | 249 | // IsValid -- 250 | func (x *Fr) IsValid() bool { 251 | return C.mclBnFr_isValid(x.getPointer()) == 1 252 | } 253 | 254 | // IsOne -- 255 | func (x *Fr) IsOne() bool { 256 | return C.mclBnFr_isOne(x.getPointer()) == 1 257 | } 258 | 259 | // IsOdd -- 260 | func (x *Fr) IsOdd() bool { 261 | return C.mclBnFr_isOdd(x.getPointer()) == 1 262 | } 263 | 264 | // IsNegative -- true if x >= (r + 1) / 2 265 | func (x *Fr) IsNegative() bool { 266 | return C.mclBnFr_isNegative(x.getPointer()) == 1 267 | } 268 | 269 | // SetByCSPRNG -- 270 | func (x *Fr) SetByCSPRNG() { 271 | err := C.mclBnFr_setByCSPRNG(x.getPointer()) 272 | if err != 0 { 273 | panic("err mclBnFr_setByCSPRNG") 274 | } 275 | } 276 | 277 | // SetHashOf -- 278 | func (x *Fr) SetHashOf(buf []byte) bool { 279 | // #nosec 280 | return C.mclBnFr_setHashOf(x.getPointer(), getPointer(buf), C.size_t(len(buf))) == 0 281 | } 282 | 283 | // GetString -- 284 | func (x *Fr) GetString(base int) string { 285 | buf := make([]byte, 2048) 286 | // #nosec 287 | n := C.mclBnFr_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) 288 | if n == 0 { 289 | panic("err mclBnFr_getStr") 290 | } 291 | return string(buf[:n]) 292 | } 293 | 294 | // Serialize -- 295 | func (x *Fr) Serialize() []byte { 296 | buf := make([]byte, 2048) 297 | // #nosec 298 | n := C.mclBnFr_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) 299 | if n == 0 { 300 | panic("err mclBnFr_serialize") 301 | } 302 | return buf[:n] 303 | } 304 | 305 | // FrNeg -- 306 | func FrNeg(out *Fr, x *Fr) { 307 | C.mclBnFr_neg(out.getPointer(), x.getPointer()) 308 | } 309 | 310 | // FrInv -- 311 | func FrInv(out *Fr, x *Fr) { 312 | C.mclBnFr_inv(out.getPointer(), x.getPointer()) 313 | } 314 | 315 | // FrSqr -- 316 | func FrSqr(out *Fr, x *Fr) { 317 | C.mclBnFr_sqr(out.getPointer(), x.getPointer()) 318 | } 319 | 320 | // FrAdd -- 321 | func FrAdd(out *Fr, x *Fr, y *Fr) { 322 | C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer()) 323 | } 324 | 325 | // FrSub -- 326 | func FrSub(out *Fr, x *Fr, y *Fr) { 327 | C.mclBnFr_sub(out.getPointer(), x.getPointer(), y.getPointer()) 328 | } 329 | 330 | // FrMul -- 331 | func FrMul(out *Fr, x *Fr, y *Fr) { 332 | C.mclBnFr_mul(out.getPointer(), x.getPointer(), y.getPointer()) 333 | } 334 | 335 | // FrDiv -- 336 | func FrDiv(out *Fr, x *Fr, y *Fr) { 337 | C.mclBnFr_div(out.getPointer(), x.getPointer(), y.getPointer()) 338 | } 339 | 340 | // FrSquareRoot -- 341 | func FrSquareRoot(out *Fr, x *Fr) bool { 342 | return C.mclBnFr_squareRoot(out.getPointer(), x.getPointer()) == 0 343 | } 344 | 345 | // Fp -- 346 | type Fp struct { 347 | v C.mclBnFp 348 | } 349 | 350 | // getPointer -- 351 | func (x *Fp) getPointer() (p *C.mclBnFp) { 352 | // #nosec 353 | return (*C.mclBnFp)(unsafe.Pointer(x)) 354 | } 355 | 356 | // Clear -- 357 | func (x *Fp) Clear() { 358 | // #nosec 359 | C.mclBnFp_clear(x.getPointer()) 360 | } 361 | 362 | // SetInt64 -- 363 | func (x *Fp) SetInt64(v int64) { 364 | // #nosec 365 | C.mclBnFp_setInt(x.getPointer(), C.int64_t(v)) 366 | } 367 | 368 | // SetString -- 369 | func (x *Fp) SetString(s string, base int) error { 370 | buf := []byte(s) 371 | // #nosec 372 | err := C.mclBnFp_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base)) 373 | if err != 0 { 374 | return fmt.Errorf("err mclBnFp_setStr %x", err) 375 | } 376 | return nil 377 | } 378 | 379 | // Deserialize -- 380 | func (x *Fp) Deserialize(buf []byte) error { 381 | // #nosec 382 | n := C.mclBnFp_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 383 | if n == 0 || int(n) != len(buf) { 384 | return fmt.Errorf("err mclBnFp_deserialize %x", buf) 385 | } 386 | return nil 387 | } 388 | 389 | // SetLittleEndian -- 390 | func (x *Fp) SetLittleEndian(buf []byte) error { 391 | // #nosec 392 | err := C.mclBnFp_setLittleEndian(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 393 | if err != 0 { 394 | return fmt.Errorf("err mclBnFp_setLittleEndian %x", err) 395 | } 396 | return nil 397 | } 398 | 399 | // SetLittleEndianMod -- 400 | func (x *Fp) SetLittleEndianMod(buf []byte) error { 401 | // #nosec 402 | err := C.mclBnFp_setLittleEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 403 | if err != 0 { 404 | return fmt.Errorf("err mclBnFp_setLittleEndianMod %x", err) 405 | } 406 | return nil 407 | } 408 | 409 | // SetBigEndianMod -- 410 | func (x *Fp) SetBigEndianMod(buf []byte) error { 411 | // #nosec 412 | err := C.mclBnFp_setBigEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 413 | if err != 0 { 414 | return fmt.Errorf("err mclBnFp_setBigEndianMod %x", err) 415 | } 416 | return nil 417 | } 418 | 419 | // IsEqual -- 420 | func (x *Fp) IsEqual(rhs *Fp) bool { 421 | return C.mclBnFp_isEqual(x.getPointer(), rhs.getPointer()) == 1 422 | } 423 | 424 | // IsZero -- 425 | func (x *Fp) IsZero() bool { 426 | return C.mclBnFp_isZero(x.getPointer()) == 1 427 | } 428 | 429 | // IsValid -- 430 | func (x *Fp) IsValid() bool { 431 | return C.mclBnFp_isValid(x.getPointer()) == 1 432 | } 433 | 434 | // IsOne -- 435 | func (x *Fp) IsOne() bool { 436 | return C.mclBnFp_isOne(x.getPointer()) == 1 437 | } 438 | 439 | // IsOdd -- 440 | func (x *Fp) IsOdd() bool { 441 | return C.mclBnFp_isOdd(x.getPointer()) == 1 442 | } 443 | 444 | // IsNegative -- true if x >= (p + 1) / 2 445 | func (x *Fp) IsNegative() bool { 446 | return C.mclBnFp_isNegative(x.getPointer()) == 1 447 | } 448 | 449 | // SetByCSPRNG -- 450 | func (x *Fp) SetByCSPRNG() { 451 | err := C.mclBnFp_setByCSPRNG(x.getPointer()) 452 | if err != 0 { 453 | panic("err mclBnFp_setByCSPRNG") 454 | } 455 | } 456 | 457 | // SetHashOf -- 458 | func (x *Fp) SetHashOf(buf []byte) bool { 459 | // #nosec 460 | return C.mclBnFp_setHashOf(x.getPointer(), getPointer(buf), C.size_t(len(buf))) == 0 461 | } 462 | 463 | // GetString -- 464 | func (x *Fp) GetString(base int) string { 465 | buf := make([]byte, 2048) 466 | // #nosec 467 | n := C.mclBnFp_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) 468 | if n == 0 { 469 | panic("err mclBnFp_getStr") 470 | } 471 | return string(buf[:n]) 472 | } 473 | 474 | // Serialize -- 475 | func (x *Fp) Serialize() []byte { 476 | buf := make([]byte, 2048) 477 | // #nosec 478 | n := C.mclBnFp_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) 479 | if n == 0 { 480 | panic("err mclBnFp_serialize") 481 | } 482 | return buf[:n] 483 | } 484 | 485 | // FpNeg -- 486 | func FpNeg(out *Fp, x *Fp) { 487 | C.mclBnFp_neg(out.getPointer(), x.getPointer()) 488 | } 489 | 490 | // FpInv -- 491 | func FpInv(out *Fp, x *Fp) { 492 | C.mclBnFp_inv(out.getPointer(), x.getPointer()) 493 | } 494 | 495 | // FpSqr -- 496 | func FpSqr(out *Fp, x *Fp) { 497 | C.mclBnFp_sqr(out.getPointer(), x.getPointer()) 498 | } 499 | 500 | // FpAdd -- 501 | func FpAdd(out *Fp, x *Fp, y *Fp) { 502 | C.mclBnFp_add(out.getPointer(), x.getPointer(), y.getPointer()) 503 | } 504 | 505 | // FpSub -- 506 | func FpSub(out *Fp, x *Fp, y *Fp) { 507 | C.mclBnFp_sub(out.getPointer(), x.getPointer(), y.getPointer()) 508 | } 509 | 510 | // FpMul -- 511 | func FpMul(out *Fp, x *Fp, y *Fp) { 512 | C.mclBnFp_mul(out.getPointer(), x.getPointer(), y.getPointer()) 513 | } 514 | 515 | // FpDiv -- 516 | func FpDiv(out *Fp, x *Fp, y *Fp) { 517 | C.mclBnFp_div(out.getPointer(), x.getPointer(), y.getPointer()) 518 | } 519 | 520 | // FpSquareRoot -- 521 | func FpSquareRoot(out *Fp, x *Fp) bool { 522 | return C.mclBnFp_squareRoot(out.getPointer(), x.getPointer()) == 0 523 | } 524 | 525 | // Fp2 -- x = D[0] + D[1] i where i^2 = -1 526 | type Fp2 struct { 527 | D [2]Fp 528 | } 529 | 530 | // getPointer -- 531 | func (x *Fp2) getPointer() (p *C.mclBnFp2) { 532 | // #nosec 533 | return (*C.mclBnFp2)(unsafe.Pointer(x)) 534 | } 535 | 536 | // Clear -- 537 | func (x *Fp2) Clear() { 538 | // #nosec 539 | C.mclBnFp2_clear(x.getPointer()) 540 | } 541 | 542 | // Deserialize -- 543 | func (x *Fp2) Deserialize(buf []byte) error { 544 | // #nosec 545 | n := C.mclBnFp2_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 546 | if n == 0 || int(n) != len(buf) { 547 | return fmt.Errorf("err mclBnFp2_deserialize %x", buf) 548 | } 549 | return nil 550 | } 551 | 552 | // IsEqual -- 553 | func (x *Fp2) IsEqual(rhs *Fp2) bool { 554 | return C.mclBnFp2_isEqual(x.getPointer(), rhs.getPointer()) == 1 555 | } 556 | 557 | // IsZero -- 558 | func (x *Fp2) IsZero() bool { 559 | return C.mclBnFp2_isZero(x.getPointer()) == 1 560 | } 561 | 562 | // IsOne -- 563 | func (x *Fp2) IsOne() bool { 564 | return C.mclBnFp2_isOne(x.getPointer()) == 1 565 | } 566 | 567 | // Serialize -- 568 | func (x *Fp2) Serialize() []byte { 569 | buf := make([]byte, 2048) 570 | // #nosec 571 | n := C.mclBnFp2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) 572 | if n == 0 { 573 | panic("err mclBnFp2_serialize") 574 | } 575 | return buf[:n] 576 | } 577 | 578 | // Fp2Neg -- 579 | func Fp2Neg(out *Fp2, x *Fp2) { 580 | C.mclBnFp2_neg(out.getPointer(), x.getPointer()) 581 | } 582 | 583 | // Fp2Inv -- 584 | func Fp2Inv(out *Fp2, x *Fp2) { 585 | C.mclBnFp2_inv(out.getPointer(), x.getPointer()) 586 | } 587 | 588 | // Fp2Sqr -- 589 | func Fp2Sqr(out *Fp2, x *Fp2) { 590 | C.mclBnFp2_sqr(out.getPointer(), x.getPointer()) 591 | } 592 | 593 | // Fp2Add -- 594 | func Fp2Add(out *Fp2, x *Fp2, y *Fp2) { 595 | C.mclBnFp2_add(out.getPointer(), x.getPointer(), y.getPointer()) 596 | } 597 | 598 | // Fp2Sub -- 599 | func Fp2Sub(out *Fp2, x *Fp2, y *Fp2) { 600 | C.mclBnFp2_sub(out.getPointer(), x.getPointer(), y.getPointer()) 601 | } 602 | 603 | // Fp2Mul -- 604 | func Fp2Mul(out *Fp2, x *Fp2, y *Fp2) { 605 | C.mclBnFp2_mul(out.getPointer(), x.getPointer(), y.getPointer()) 606 | } 607 | 608 | // Fp2Div -- 609 | func Fp2Div(out *Fp2, x *Fp2, y *Fp2) { 610 | C.mclBnFp2_div(out.getPointer(), x.getPointer(), y.getPointer()) 611 | } 612 | 613 | // Fp2SquareRoot -- 614 | func Fp2SquareRoot(out *Fp2, x *Fp2) bool { 615 | return C.mclBnFp2_squareRoot(out.getPointer(), x.getPointer()) == 0 616 | } 617 | 618 | // G1 -- 619 | type G1 struct { 620 | X Fp 621 | Y Fp 622 | Z Fp 623 | } 624 | 625 | // getPointer -- 626 | func (x *G1) getPointer() (p *C.mclBnG1) { 627 | // #nosec 628 | return (*C.mclBnG1)(unsafe.Pointer(x)) 629 | } 630 | 631 | // Clear -- 632 | func (x *G1) Clear() { 633 | // #nosec 634 | C.mclBnG1_clear(x.getPointer()) 635 | } 636 | 637 | // SetString -- 638 | func (x *G1) SetString(s string, base int) error { 639 | buf := []byte(s) 640 | // #nosec 641 | err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base)) 642 | if err != 0 { 643 | return fmt.Errorf("err mclBnG1_setStr %x", err) 644 | } 645 | return nil 646 | } 647 | 648 | // Deserialize -- 649 | func (x *G1) Deserialize(buf []byte) error { 650 | // #nosec 651 | n := C.mclBnG1_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 652 | if n == 0 || int(n) != len(buf) { 653 | return fmt.Errorf("err mclBnG1_deserialize %x", buf) 654 | } 655 | return nil 656 | } 657 | 658 | const ZERO_HEADER = 1 << 6 659 | 660 | func isZeroFormat(buf []byte, n int) bool { 661 | if len(buf) < n { 662 | return false 663 | } 664 | if buf[0] != ZERO_HEADER { 665 | return false 666 | } 667 | for i := 1; i < n; i++ { 668 | if buf[i] != 0 { 669 | return false 670 | } 671 | } 672 | return true 673 | } 674 | 675 | // DeserializeUncompressed -- x.Deserialize() + y.Deserialize() 676 | func (x *G1) DeserializeUncompressed(buf []byte) error { 677 | if isZeroFormat(buf, GetG1ByteSize()*2) { 678 | x.Clear() 679 | return nil 680 | } 681 | // #nosec 682 | var n = C.mclBnFp_deserialize(x.X.getPointer(), getPointer(buf), C.size_t(len(buf))) 683 | if n == 0 { 684 | return fmt.Errorf("err UncompressedDeserialize X %x", buf) 685 | } 686 | buf = buf[n:] 687 | // #nosec 688 | n = C.mclBnFp_deserialize(x.Y.getPointer(), getPointer(buf), C.size_t(len(buf))) 689 | if n == 0 { 690 | return fmt.Errorf("err UncompressedDeserialize Y %x", buf) 691 | } 692 | x.Z.SetInt64(1) 693 | if !x.IsValid() { 694 | return fmt.Errorf("err invalid point") 695 | } 696 | return nil 697 | } 698 | 699 | // IsEqual -- 700 | func (x *G1) IsEqual(rhs *G1) bool { 701 | return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1 702 | } 703 | 704 | // IsZero -- 705 | func (x *G1) IsZero() bool { 706 | return C.mclBnG1_isZero(x.getPointer()) == 1 707 | } 708 | 709 | // IsValid -- 710 | func (x *G1) IsValid() bool { 711 | return C.mclBnG1_isValid(x.getPointer()) == 1 712 | } 713 | 714 | // IsValidOrder -- 715 | func (x *G1) IsValidOrder() bool { 716 | return C.mclBnG1_isValidOrder(x.getPointer()) == 1 717 | } 718 | 719 | // HashAndMapTo -- 720 | func (x *G1) HashAndMapTo(buf []byte) error { 721 | // #nosec 722 | err := C.mclBnG1_hashAndMapTo(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 723 | if err != 0 { 724 | return fmt.Errorf("err mclBnG1_hashAndMapTo %x", err) 725 | } 726 | return nil 727 | } 728 | 729 | // GetString -- 730 | func (x *G1) GetString(base int) string { 731 | buf := make([]byte, 2048) 732 | // #nosec 733 | n := C.mclBnG1_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) 734 | if n == 0 { 735 | panic("err mclBnG1_getStr") 736 | } 737 | return string(buf[:n]) 738 | } 739 | 740 | // Serialize -- 741 | func (x *G1) Serialize() []byte { 742 | buf := make([]byte, GetG1ByteSize()) 743 | // #nosec 744 | n := C.mclBnG1_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) 745 | if n == 0 { 746 | panic("err mclBnG1_serialize") 747 | } 748 | return buf 749 | } 750 | 751 | // SerializeUncompressed -- all zero array if x.IsZero() 752 | func (x *G1) SerializeUncompressed() []byte { 753 | buf := make([]byte, GetG1ByteSize()*2) 754 | if x.IsZero() { 755 | buf[0] = ZERO_HEADER 756 | return buf 757 | } 758 | var nx G1 759 | G1Normalize(&nx, x) 760 | // #nosec 761 | var n = C.mclBnFp_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), nx.X.getPointer()) 762 | if n == 0 { 763 | panic("err mclBnFp_serialize X") 764 | } 765 | n = C.mclBnFp_serialize(unsafe.Pointer(&buf[n]), C.size_t(len(buf))-n, nx.Y.getPointer()) 766 | if n == 0 { 767 | panic("err mclBnFp_serialize Y") 768 | } 769 | return buf 770 | } 771 | 772 | // G1Normalize -- 773 | func G1Normalize(out *G1, x *G1) { 774 | C.mclBnG1_normalize(out.getPointer(), x.getPointer()) 775 | } 776 | 777 | // G1Neg -- 778 | func G1Neg(out *G1, x *G1) { 779 | C.mclBnG1_neg(out.getPointer(), x.getPointer()) 780 | } 781 | 782 | // G1Dbl -- 783 | func G1Dbl(out *G1, x *G1) { 784 | C.mclBnG1_dbl(out.getPointer(), x.getPointer()) 785 | } 786 | 787 | // G1Add -- 788 | func G1Add(out *G1, x *G1, y *G1) { 789 | C.mclBnG1_add(out.getPointer(), x.getPointer(), y.getPointer()) 790 | } 791 | 792 | // G1Sub -- 793 | func G1Sub(out *G1, x *G1, y *G1) { 794 | C.mclBnG1_sub(out.getPointer(), x.getPointer(), y.getPointer()) 795 | } 796 | 797 | // G1Mul -- 798 | func G1Mul(out *G1, x *G1, y *Fr) { 799 | C.mclBnG1_mul(out.getPointer(), x.getPointer(), y.getPointer()) 800 | } 801 | 802 | // G1MulVec -- multi scalar multiplication out = sum mul(xVec[i], yVec[i]) 803 | func G1MulVec(out *G1, xVec []G1, yVec []Fr) { 804 | n := len(xVec) 805 | if n != len(yVec) { 806 | panic("xVec and yVec have the same size") 807 | } 808 | if n == 0 { 809 | out.Clear() 810 | return 811 | } 812 | C.mclBnG1_mulVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n)) 813 | } 814 | 815 | // G1MulCT -- constant time (depending on bit lengh of y) 816 | func G1MulCT(out *G1, x *G1, y *Fr) { 817 | C.mclBnG1_mulCT(out.getPointer(), x.getPointer(), y.getPointer()) 818 | } 819 | 820 | // G2 -- 821 | type G2 struct { 822 | X Fp2 823 | Y Fp2 824 | Z Fp2 825 | } 826 | 827 | // getPointer -- 828 | func (x *G2) getPointer() (p *C.mclBnG2) { 829 | // #nosec 830 | return (*C.mclBnG2)(unsafe.Pointer(x)) 831 | } 832 | 833 | // Clear -- 834 | func (x *G2) Clear() { 835 | // #nosec 836 | C.mclBnG2_clear(x.getPointer()) 837 | } 838 | 839 | // SetString -- 840 | func (x *G2) SetString(s string, base int) error { 841 | buf := []byte(s) 842 | // #nosec 843 | err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base)) 844 | if err != 0 { 845 | return fmt.Errorf("err mclBnG2_setStr %x", err) 846 | } 847 | return nil 848 | } 849 | 850 | // Deserialize -- 851 | func (x *G2) Deserialize(buf []byte) error { 852 | // #nosec 853 | n := C.mclBnG2_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 854 | if n == 0 || int(n) != len(buf) { 855 | return fmt.Errorf("err mclBnG2_deserialize %x", buf) 856 | } 857 | return nil 858 | } 859 | 860 | // DeserializeUncompressed -- x.Deserialize() + y.Deserialize() 861 | func (x *G2) DeserializeUncompressed(buf []byte) error { 862 | if isZeroFormat(buf, GetG2ByteSize()*2) { 863 | x.Clear() 864 | return nil 865 | } 866 | // #nosec 867 | var n = C.mclBnFp2_deserialize(x.X.getPointer(), getPointer(buf), C.size_t(len(buf))) 868 | if n == 0 { 869 | return fmt.Errorf("err UncompressedDeserialize X %x", buf) 870 | } 871 | buf = buf[n:] 872 | // #nosec 873 | n = C.mclBnFp2_deserialize(x.Y.getPointer(), getPointer(buf), C.size_t(len(buf))) 874 | if n == 0 { 875 | return fmt.Errorf("err UncompressedDeserialize Y %x", buf) 876 | } 877 | x.Z.D[0].SetInt64(1) 878 | x.Z.D[1].Clear() 879 | if !x.IsValid() { 880 | return fmt.Errorf("err invalid point") 881 | } 882 | return nil 883 | } 884 | 885 | // IsEqual -- 886 | func (x *G2) IsEqual(rhs *G2) bool { 887 | return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1 888 | } 889 | 890 | // IsZero -- 891 | func (x *G2) IsZero() bool { 892 | return C.mclBnG2_isZero(x.getPointer()) == 1 893 | } 894 | 895 | // IsValid -- 896 | func (x *G2) IsValid() bool { 897 | return C.mclBnG2_isValid(x.getPointer()) == 1 898 | } 899 | 900 | // IsValidOrder -- 901 | func (x *G2) IsValidOrder() bool { 902 | return C.mclBnG2_isValidOrder(x.getPointer()) == 1 903 | } 904 | 905 | // HashAndMapTo -- 906 | func (x *G2) HashAndMapTo(buf []byte) error { 907 | // #nosec 908 | err := C.mclBnG2_hashAndMapTo(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 909 | if err != 0 { 910 | return fmt.Errorf("err mclBnG2_hashAndMapTo %x", err) 911 | } 912 | return nil 913 | } 914 | 915 | // GetString -- 916 | func (x *G2) GetString(base int) string { 917 | buf := make([]byte, 2048) 918 | // #nosec 919 | n := C.mclBnG2_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) 920 | if n == 0 { 921 | panic("err mclBnG2_getStr") 922 | } 923 | return string(buf[:n]) 924 | } 925 | 926 | // Serialize -- 927 | func (x *G2) Serialize() []byte { 928 | buf := make([]byte, 2048) 929 | // #nosec 930 | n := C.mclBnG2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) 931 | if n == 0 { 932 | panic("err mclBnG2_serialize") 933 | } 934 | return buf[:n] 935 | } 936 | 937 | // SerializeUncompressed -- all zero array if x.IsZero() 938 | func (x *G2) SerializeUncompressed() []byte { 939 | buf := make([]byte, GetG2ByteSize()*2) 940 | if x.IsZero() { 941 | buf[0] = ZERO_HEADER 942 | return buf 943 | } 944 | var nx G2 945 | G2Normalize(&nx, x) 946 | // #nosec 947 | var n = C.mclBnFp2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), nx.X.getPointer()) 948 | if n == 0 { 949 | panic("err mclBnFp2_serialize X") 950 | } 951 | n = C.mclBnFp2_serialize(unsafe.Pointer(&buf[n]), C.size_t(len(buf))-n, nx.Y.getPointer()) 952 | if n == 0 { 953 | panic("err mclBnFp2_serialize Y") 954 | } 955 | return buf 956 | } 957 | 958 | // G2Normalize -- 959 | func G2Normalize(out *G2, x *G2) { 960 | C.mclBnG2_normalize(out.getPointer(), x.getPointer()) 961 | } 962 | 963 | // G2Neg -- 964 | func G2Neg(out *G2, x *G2) { 965 | C.mclBnG2_neg(out.getPointer(), x.getPointer()) 966 | } 967 | 968 | // G2Dbl -- 969 | func G2Dbl(out *G2, x *G2) { 970 | C.mclBnG2_dbl(out.getPointer(), x.getPointer()) 971 | } 972 | 973 | // G2Add -- 974 | func G2Add(out *G2, x *G2, y *G2) { 975 | C.mclBnG2_add(out.getPointer(), x.getPointer(), y.getPointer()) 976 | } 977 | 978 | // G2Sub -- 979 | func G2Sub(out *G2, x *G2, y *G2) { 980 | C.mclBnG2_sub(out.getPointer(), x.getPointer(), y.getPointer()) 981 | } 982 | 983 | // G2Mul -- 984 | func G2Mul(out *G2, x *G2, y *Fr) { 985 | C.mclBnG2_mul(out.getPointer(), x.getPointer(), y.getPointer()) 986 | } 987 | 988 | // G2MulVec -- multi scalar multiplication out = sum mul(xVec[i], yVec[i]) 989 | func G2MulVec(out *G2, xVec []G2, yVec []Fr) { 990 | n := len(xVec) 991 | if n != len(yVec) { 992 | panic("xVec and yVec have the same size") 993 | } 994 | if n == 0 { 995 | out.Clear() 996 | return 997 | } 998 | C.mclBnG2_mulVec(out.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n)) 999 | } 1000 | 1001 | // GT -- 1002 | type GT struct { 1003 | v C.mclBnGT 1004 | } 1005 | 1006 | // getPointer -- 1007 | func (x *GT) getPointer() (p *C.mclBnGT) { 1008 | // #nosec 1009 | return (*C.mclBnGT)(unsafe.Pointer(x)) 1010 | } 1011 | 1012 | // Clear -- 1013 | func (x *GT) Clear() { 1014 | // #nosec 1015 | C.mclBnGT_clear(x.getPointer()) 1016 | } 1017 | 1018 | // SetInt64 -- 1019 | func (x *GT) SetInt64(v int64) { 1020 | // #nosec 1021 | C.mclBnGT_setInt(x.getPointer(), C.int64_t(v)) 1022 | } 1023 | 1024 | // SetString -- 1025 | func (x *GT) SetString(s string, base int) error { 1026 | buf := []byte(s) 1027 | // #nosec 1028 | err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base)) 1029 | if err != 0 { 1030 | return fmt.Errorf("err mclBnGT_setStr %x", err) 1031 | } 1032 | return nil 1033 | } 1034 | 1035 | // Deserialize -- 1036 | func (x *GT) Deserialize(buf []byte) error { 1037 | // #nosec 1038 | n := C.mclBnGT_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf))) 1039 | if n == 0 || int(n) != len(buf) { 1040 | return fmt.Errorf("err mclBnGT_deserialize %x", buf) 1041 | } 1042 | return nil 1043 | } 1044 | 1045 | // IsEqual -- 1046 | func (x *GT) IsEqual(rhs *GT) bool { 1047 | return C.mclBnGT_isEqual(x.getPointer(), rhs.getPointer()) == 1 1048 | } 1049 | 1050 | // IsZero -- 1051 | func (x *GT) IsZero() bool { 1052 | return C.mclBnGT_isZero(x.getPointer()) == 1 1053 | } 1054 | 1055 | // IsOne -- 1056 | func (x *GT) IsOne() bool { 1057 | return C.mclBnGT_isOne(x.getPointer()) == 1 1058 | } 1059 | 1060 | // GetString -- 1061 | func (x *GT) GetString(base int) string { 1062 | buf := make([]byte, 2048) 1063 | // #nosec 1064 | n := C.mclBnGT_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) 1065 | if n == 0 { 1066 | panic("err mclBnGT_getStr") 1067 | } 1068 | return string(buf[:n]) 1069 | } 1070 | 1071 | // Serialize -- 1072 | func (x *GT) Serialize() []byte { 1073 | buf := make([]byte, 2048) 1074 | // #nosec 1075 | n := C.mclBnGT_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) 1076 | if n == 0 { 1077 | panic("err mclBnGT_serialize") 1078 | } 1079 | return buf[:n] 1080 | } 1081 | 1082 | // GTNeg -- 1083 | func GTNeg(out *GT, x *GT) { 1084 | C.mclBnGT_neg(out.getPointer(), x.getPointer()) 1085 | } 1086 | 1087 | // GTInv -- 1088 | func GTInv(out *GT, x *GT) { 1089 | C.mclBnGT_inv(out.getPointer(), x.getPointer()) 1090 | } 1091 | 1092 | // GTAdd -- 1093 | func GTAdd(out *GT, x *GT, y *GT) { 1094 | C.mclBnGT_add(out.getPointer(), x.getPointer(), y.getPointer()) 1095 | } 1096 | 1097 | // GTSub -- 1098 | func GTSub(out *GT, x *GT, y *GT) { 1099 | C.mclBnGT_sub(out.getPointer(), x.getPointer(), y.getPointer()) 1100 | } 1101 | 1102 | // GTMul -- 1103 | func GTMul(out *GT, x *GT, y *GT) { 1104 | C.mclBnGT_mul(out.getPointer(), x.getPointer(), y.getPointer()) 1105 | } 1106 | 1107 | // GTDiv -- 1108 | func GTDiv(out *GT, x *GT, y *GT) { 1109 | C.mclBnGT_div(out.getPointer(), x.getPointer(), y.getPointer()) 1110 | } 1111 | 1112 | // GTPow -- 1113 | func GTPow(out *GT, x *GT, y *Fr) { 1114 | C.mclBnGT_pow(out.getPointer(), x.getPointer(), y.getPointer()) 1115 | } 1116 | 1117 | // MapToG1 -- 1118 | func MapToG1(out *G1, x *Fp) error { 1119 | if C.mclBnFp_mapToG1(out.getPointer(), x.getPointer()) != 0 { 1120 | return fmt.Errorf("err mclBnFp_mapToG1") 1121 | } 1122 | return nil 1123 | } 1124 | 1125 | // MapToG2 -- 1126 | func MapToG2(out *G2, x *Fp2) error { 1127 | if C.mclBnFp2_mapToG2(out.getPointer(), x.getPointer()) != 0 { 1128 | return fmt.Errorf("err mclBnFp2_mapToG2") 1129 | } 1130 | return nil 1131 | } 1132 | 1133 | // Pairing -- 1134 | func Pairing(out *GT, x *G1, y *G2) { 1135 | C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer()) 1136 | } 1137 | 1138 | // FinalExp -- 1139 | func FinalExp(out *GT, x *GT) { 1140 | C.mclBn_finalExp(out.getPointer(), x.getPointer()) 1141 | } 1142 | 1143 | // MillerLoop -- 1144 | func MillerLoop(out *GT, x *G1, y *G2) { 1145 | C.mclBn_millerLoop(out.getPointer(), x.getPointer(), y.getPointer()) 1146 | } 1147 | 1148 | // MillerLoopVec -- multi pairings ; out = prod_i e(xVec[i], yVec[i]) 1149 | func MillerLoopVec(out *GT, xVec []G1, yVec []G2) { 1150 | n := len(xVec) 1151 | if n != len(yVec) { 1152 | panic("xVec and yVec have the same size") 1153 | } 1154 | if n == 0 { 1155 | out.SetInt64(1) 1156 | return 1157 | } 1158 | C.mclBn_millerLoopVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(n)) 1159 | } 1160 | 1161 | // GetUint64NumToPrecompute -- 1162 | func GetUint64NumToPrecompute() int { 1163 | return int(C.mclBn_getUint64NumToPrecompute()) 1164 | } 1165 | 1166 | // PrecomputeG2 -- 1167 | func PrecomputeG2(Qbuf []uint64, Q *G2) { 1168 | // #nosec 1169 | C.mclBn_precomputeG2((*C.uint64_t)(unsafe.Pointer(&Qbuf[0])), Q.getPointer()) 1170 | } 1171 | 1172 | // PrecomputedMillerLoop -- 1173 | func PrecomputedMillerLoop(out *GT, P *G1, Qbuf []uint64) { 1174 | // #nosec 1175 | C.mclBn_precomputedMillerLoop(out.getPointer(), P.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Qbuf[0]))) 1176 | } 1177 | 1178 | // PrecomputedMillerLoop2 -- 1179 | func PrecomputedMillerLoop2(out *GT, P1 *G1, Q1buf []uint64, P2 *G1, Q2buf []uint64) { 1180 | // #nosec 1181 | C.mclBn_precomputedMillerLoop2(out.getPointer(), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0])), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0]))) 1182 | } 1183 | 1184 | // FrEvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... 1185 | func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error { 1186 | n := len(c) 1187 | if n == 0 { 1188 | y.Clear() 1189 | return nil 1190 | } 1191 | // #nosec 1192 | err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer()) 1193 | if err != 0 { 1194 | return fmt.Errorf("err mclBn_FrEvaluatePolynomial") 1195 | } 1196 | return nil 1197 | } 1198 | 1199 | // G1EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... 1200 | func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error { 1201 | n := len(c) 1202 | if n == 0 { 1203 | y.Clear() 1204 | return nil 1205 | } 1206 | // #nosec 1207 | err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer()) 1208 | if err != 0 { 1209 | return fmt.Errorf("err mclBn_G1EvaluatePolynomial") 1210 | } 1211 | return nil 1212 | } 1213 | 1214 | // G2EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... 1215 | func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error { 1216 | n := len(c) 1217 | if n == 0 { 1218 | y.Clear() 1219 | return nil 1220 | } 1221 | // #nosec 1222 | err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer()) 1223 | if err != 0 { 1224 | return fmt.Errorf("err mclBn_G2EvaluatePolynomial") 1225 | } 1226 | return nil 1227 | } 1228 | 1229 | // FrLagrangeInterpolation -- 1230 | func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error { 1231 | n := len(xVec) 1232 | if n == 0 { 1233 | return fmt.Errorf("err FrLagrangeInterpolation:n=0") 1234 | } 1235 | if n != len(yVec) { 1236 | return fmt.Errorf("err FrLagrangeInterpolation:bad size") 1237 | } 1238 | // #nosec 1239 | err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n)) 1240 | if err != 0 { 1241 | return fmt.Errorf("err FrLagrangeInterpolation") 1242 | } 1243 | return nil 1244 | } 1245 | 1246 | // G1LagrangeInterpolation -- 1247 | func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error { 1248 | n := len(xVec) 1249 | if n == 0 { 1250 | return fmt.Errorf("err G1LagrangeInterpolation:n=0") 1251 | } 1252 | if n != len(yVec) { 1253 | return fmt.Errorf("err G1LagrangeInterpolation:bad size") 1254 | } 1255 | // #nosec 1256 | err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(n)) 1257 | if err != 0 { 1258 | return fmt.Errorf("err G1LagrangeInterpolation") 1259 | } 1260 | return nil 1261 | } 1262 | 1263 | // G2LagrangeInterpolation -- 1264 | func G2LagrangeInterpolation(out *G2, xVec []Fr, yVec []G2) error { 1265 | n := len(xVec) 1266 | if n == 0 { 1267 | return fmt.Errorf("err G2LagrangeInterpolation:n=0") 1268 | } 1269 | if n != len(yVec) { 1270 | return fmt.Errorf("err G2LagrangeInterpolation:bad size") 1271 | } 1272 | // #nosec 1273 | err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(n)) 1274 | if err != 0 { 1275 | return fmt.Errorf("err G2LagrangeInterpolation") 1276 | } 1277 | return nil 1278 | } 1279 | -------------------------------------------------------------------------------- /examples/agg-verify.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/herumi/bls-go-binary/bls" 6 | ) 7 | 8 | var g_Qcoeff []uint64 9 | 10 | func initQcoeff() { 11 | bls.Init(bls.BLS12_381) 12 | n := bls.GetUint64NumToPrecompute() 13 | g_Qcoeff = make([]uint64, n) 14 | var Q bls.PublicKey 15 | bls.BlsGetGeneratorOfPublicKey(&Q) 16 | bls.PrecomputeG2(g_Qcoeff, bls.CastFromPublicKey(&Q)) 17 | } 18 | 19 | func toG(h []byte) (P bls.G1) { 20 | var t bls.Fp 21 | t.SetLittleEndian(h) 22 | bls.MapToG1(&P, &t) 23 | return P 24 | } 25 | 26 | func splitVAH_init(agg *bls.Sign) (e bls.GT) { 27 | P := *bls.CastFromSign(agg) 28 | bls.G1Neg(&P, &P) 29 | bls.PrecomputedMillerLoop(&e, &P, g_Qcoeff) 30 | return e 31 | } 32 | 33 | // return the processed number 34 | func splitVAH_exec(e *bls.GT, pubs []bls.PublicKey, hs [][]byte) (m int) { 35 | N := 16 36 | g1s := make([]bls.G1, N) 37 | g2s := make([]bls.G2, N) 38 | m = len(pubs) 39 | if m > N { 40 | m = N 41 | } 42 | for i := 0; i < m; i++ { 43 | g1s[i] = toG(hs[i]) 44 | g2s[i] = *bls.CastFromPublicKey(&pubs[i]) 45 | } 46 | var e1 bls.GT 47 | bls.MillerLoopVec(&e1, g1s[0:m], g2s[0:m]) 48 | bls.GTMul(e, e, &e1) 49 | return m 50 | } 51 | 52 | func splitVAH_final(e *bls.GT) bool { 53 | bls.FinalExp(e, e) 54 | return e.IsOne() 55 | } 56 | 57 | func splitVerifyAggregateHashes(agg *bls.Sign, pubs []bls.PublicKey, hs [][]byte) bool { 58 | n := len(pubs) 59 | if n != len(hs) { 60 | return false 61 | } 62 | 63 | e := splitVAH_init(agg) 64 | for { 65 | m := splitVAH_exec(&e, pubs, hs) 66 | pubs = pubs[m:] 67 | hs = hs[m:] 68 | n = n - m 69 | if n == 0 { 70 | break 71 | } 72 | } 73 | /* 74 | N := 16 75 | g1work := make([]bls.G1, N) 76 | g2work := make([]bls.G2, N) 77 | for { 78 | m := N 79 | if n < m { 80 | m = n 81 | } 82 | for i := 0; i < m; i++ { 83 | g1work[i] = toG(hs[i]) 84 | g2work[i] = *bls.CastFromPublicKey(&pubs[i]) 85 | } 86 | var e1 bls.GT 87 | bls.MillerLoopVec(&e1, g1work[0:m], g2work[0:m]) 88 | bls.GTMul(&e, &e, &e1) 89 | pubs = pubs[m:] 90 | hs = hs[m:] 91 | n = n - m 92 | if n == 0 { 93 | break 94 | } 95 | } 96 | */ 97 | return splitVAH_final(&e) 98 | } 99 | 100 | func testVerifyAggregateHashes() { 101 | n := 100 102 | secs := make([]bls.SecretKey, n) 103 | pubs := make([]bls.PublicKey, n) 104 | hs := make([][]byte, n) 105 | sigs := make([]bls.Sign, n) 106 | for i := 0; i < n; i++ { 107 | hs[i] = make([]byte, 32) 108 | hs[i][0] = byte(i + 1) 109 | secs[i].SetByCSPRNG() 110 | pubs[i] = *secs[i].GetPublicKey() 111 | sigs[i] = *secs[i].SignHash(hs[i]) 112 | if !sigs[i].VerifyHash(&pubs[i], hs[i]) { 113 | fmt.Printf("err %v\n", i) 114 | } 115 | } 116 | var agg bls.Sign 117 | agg.Aggregate(sigs) 118 | fmt.Printf("verify=%v\n", agg.VerifyAggregateHashes(pubs, hs)) 119 | fmt.Printf("verify split=%v\n", splitVerifyAggregateHashes(&agg, pubs, hs)) 120 | } 121 | 122 | func main() { 123 | initQcoeff() 124 | testVerifyAggregateHashes() 125 | } 126 | -------------------------------------------------------------------------------- /examples/cast-sample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/herumi/bls-go-binary/bls" 6 | ) 7 | 8 | func PutPub(pub *bls.PublicKey) { 9 | g2 := bls.CastFromPublicKey(pub) 10 | bls.G2Normalize(g2, g2) 11 | fmt.Println("x.a", g2.X.D[0].GetString(16)) 12 | fmt.Println("x.b", g2.X.D[1].GetString(16)) 13 | fmt.Println("y.a", g2.Y.D[0].GetString(16)) 14 | fmt.Println("y.b", g2.Y.D[1].GetString(16)) 15 | } 16 | 17 | func main() { 18 | bls.Init(bls.CurveFp254BNb) 19 | var sk bls.SecretKey 20 | sk.SetHexString("1") 21 | pk := sk.GetPublicKey() 22 | fmt.Println("sk", sk.GetHexString()) 23 | fmt.Println("pk", pk.GetHexString()) 24 | PutPub(pk) 25 | } 26 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/herumi/bls-go-binary 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /obj/.emptydir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/herumi/bls-go-binary/aa0e1c490f2e4a7c50938dc6e7ab89fda4e202d8/obj/.emptydir -------------------------------------------------------------------------------- /patch/bls.patch: -------------------------------------------------------------------------------- 1 | --- src//bls/ffi/go/bls/bls.go 2023-01-23 17:12:37.702058891 +0900 2 | +++ bls/bls.go 2023-01-25 03:40:56.213759397 +0900 3 | @@ -1,16 +1,10 @@ 4 | package bls 5 | 6 | /* 7 | -#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4 8 | -#cgo bn256 LDFLAGS:-lbls256 9 | -#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 10 | -#cgo bn384 LDFLAGS:-lbls384 11 | -#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4 12 | -#cgo bn384_256 LDFLAGS:-lbls384_256 13 | - 14 | -#cgo LDFLAGS:-lstdc++ 15 | +#cgo CFLAGS:-I${SRCDIR}./include 16 | typedef unsigned int (*ReadRandFunc)(void *, void *, unsigned int); 17 | int wrapReadRandCgo(void *self, void *buf, unsigned int n); 18 | +#include 19 | #include 20 | */ 21 | import "C" 22 | -------------------------------------------------------------------------------- /patch/mcl.patch: -------------------------------------------------------------------------------- 1 | --- ../bls/ffi/go/bls/mcl.go 2019-10-27 11:58:06.110727404 +0900 2 | +++ bls/mcl.go 2019-11-07 12:18:49.622814576 +0900 3 | @@ -1,10 +1,8 @@ 4 | package bls 5 | 6 | /* 7 | -#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4 8 | -#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 9 | -#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4 10 | -#include 11 | +#cgo CFLAGS:-I./include 12 | +#include 13 | */ 14 | import "C" 15 | import "fmt" 16 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://github.com/herumi/bls-go-binary/actions/workflows/main.yml/badge.svg)](https://github.com/herumi/bls-go-binary/actions/workflows/main.yml) 2 | 3 | # bls with compiled static library 4 | 5 | This repository contains compiled static library of https://github.com/herumi/bls without `BLS_ETH=1`. 6 | See [releases](https://github.com/herumi/bls-go-binary/releases/). 7 | 8 | If you want the binary compatible with eth2-spec, then see [bls-eth-go-binary](https://github.com/herumi/bls-eth-go-binary). 9 | 10 | * SecretKey; Fr 11 | * PublicKey; G2 12 | * Signature; G1 13 | 14 | # News 15 | - 2023/Aug/17 The performance of Sign is a little improved. 16 | 17 | # How to run `examples/sample.go` 18 | 19 | ``` 20 | git clone -b release https://github.com/herumi/bls-go-binary 21 | cd bls-go-binary 22 | go run examples/agg-verify.go 23 | ``` 24 | 25 | # How to use `setup_vendor.sh` 26 | Since this package includes C headers and libraries, 27 | when using `go build -mod=vendor`, please run: 28 | 29 | ```bash 30 | $GOMODCACHE/github.com/herumi/bls-go-binary@/setup_vendor.sh 31 | ``` 32 | 33 | # How to build the static binary 34 | The following steps are not necessary if you use release branch. 35 | 36 | ``` 37 | git clone https://github.com/herumi/bls-go-binary 38 | cd bls-go-binary 39 | git submodule update --init --recursive 40 | go test ./bls 41 | ``` 42 | 43 | ## Linux, Mac, Windows(mingw64) 44 | On x64 Linux, 45 | ``` 46 | make 47 | ``` 48 | 49 | Otherwise, clang is necessary to build ll files. 50 | ``` 51 | make CXX=clang++ 52 | ``` 53 | 54 | ### Cross compile on macOS 55 | 56 | ``` 57 | make ARCH=x86_64 # for Intel mac 58 | make ARCH=arm64 # for M1 mac 59 | ``` 60 | 61 | ### Cross compile of aarch64 on x64 Linux 62 | 63 | ``` 64 | sudo apt-get install gcc-multilib 65 | make -C src/bls -f Makefile.onelib build_aarch64 CXX=clang++ -j OUT_DIR=../.. 66 | ``` 67 | 68 | # Android 69 | ``` 70 | make android 71 | ``` 72 | 73 | If you need a shared library, then after `make clean`, 74 | 75 | ``` 76 | make android BLS_LIB_SHARED=1 77 | ``` 78 | 79 | # iOS 80 | ``` 81 | make ios 82 | ``` 83 | 84 | # how to release (internal notification) 85 | ``` 86 | git checkout -b release 87 | git reset --hard origin/release 88 | git merge origin/master 89 | git push origin release 90 | ``` 91 | 92 | # Author 93 | 94 | MITSUNARI Shigeo(herumi@nifty.com) 95 | 96 | # Sponsors welcome 97 | [GitHub Sponsor](https://github.com/sponsors/herumi) 98 | -------------------------------------------------------------------------------- /setup_vendor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # setup vendor script 3 | 4 | set -e 5 | 6 | if [ -f "$(dirname "$0")/ETH.cfg" ]; then 7 | MODULE_NAME="bls-eth-go-binary" 8 | echo "github.com/herumi/${MODULE_NAME}" 9 | else 10 | MODULE_NAME="bls-go-binary" 11 | echo "ETH.cfg not found, using module: github.com/herumi/${MODULE_NAME}" 12 | fi 13 | 14 | MODULE="github.com/herumi/${MODULE_NAME}" 15 | echo "module : ${MODULE_NAME}" 16 | 17 | if [ $# -ge 1 ]; then 18 | VERSION="$1" 19 | echo "Using specified version: ${VERSION}" 20 | else 21 | VERSION=$(go list -m -f '{{.Version}}' ${MODULE}) 22 | fi 23 | 24 | if [ -z "$VERSION" ]; then 25 | echo "Error: Could not determine module version. Please add the module to go.mod or specify version as argument." 26 | echo "Usage: $0 [version]" 27 | echo "Example: $0 v1.36.4" 28 | exit 1 29 | fi 30 | 31 | GOPATH=$(go env GOPATH) 32 | MODULE_PATH="${GOPATH}/pkg/mod/${MODULE}@${VERSION}" 33 | 34 | go mod vendor 35 | 36 | mkdir -p vendor/${MODULE}/bls/include 37 | mkdir -p vendor/${MODULE}/bls/lib/ 38 | 39 | cp -r "${MODULE_PATH}/bls/include/" "vendor/${MODULE}/bls/" 40 | cp -r "${MODULE_PATH}/bls/lib/" "vendor/${MODULE}/bls/" 41 | 42 | --------------------------------------------------------------------------------