(2)一起來讀PBC Library manual !!!

以下內容源自PBC Library 的 英文manual(Chapter 2)。

本文摘要:

一,Basics
二,Tutorial
三,BLS Signature
四,Import / Export
五,完整示例

一,Basics

Programs using the PBC library should include the file pbc.h:

#include <pbc.h>

and linked against the PBC library and the GMP library, e.g.

$ gcc program.c -L. -lpbc -lgmp

The file pbc.h already includes gmp.h.

PBC follows GMP in several respects:

• Output arguments generally precede input arguments.

• The same variable can be used as input and output in one call.

• Before a variable may be used it must be initialized exactly once. When no longer needed it must be cleared. For efficiency, unnecessary initializating and clearing should be avoided.

• PBC variables ending with _t behave the same as GMP variables in function calls: effectively as call-by references. In other words, as in GMP, if a function that modifies an input variable, that variable remains modified when control return is returned to the caller.

• Like GMP, variables automatically allocate memory when needed. By default, malloc() and friends are called but this can be changed.

• PBC functions are mostly reentrant.

Since the PBC library is built on top of GMP, the GMP types are available. PBC types are similar to GMP types. The following example is paraphrased from an example in the GMP manual, and shows how to declare the PBC data type element_t.

element_t sum;
struct foo { element_t x, y; }; 
element_t vec[20];

GMP has the mpz_t type for integers, mpq_t for rationals and so on. In contrast, PBC uses the element_t data type for elements of different algebraic structures, such as elliptic curve groups, polynomial rings and finite fields. Functions assume their inputs come from appropriate algebraic structures.

GMP具有用於整數的mpz_t類型,用於有理數的mpq_t等。 相反,PBC將element_t數據類型用於不同代數結構的元素,例如橢圓曲線羣,多項式環和有限域。 函數假定其輸入來自適當的代數結構。

PBC data types and functions can be categorized as follows. The first two alone suffice for a range PBC of applications.

PBC數據類型和功能可以分類如下。 頭兩個應用程序就可以滿足要求。

• element_t: elements of an algebraic structure.

• pairing_t: pairings where elements belong; can initialize from sample pairing parameters bundled with PBC in the param subdirectory.

【譯】
pairing_t:元素所屬的配對; 可以根據param子目錄中與PBC捆綁在一起的樣品配對參數進行初始化。

• pbc_param_t: used to generate pairing parameters.

• pbc_cm_t: parameters for constructing curves via the CM method; sometimes required by pbc_param_t.

• field_t: algebraic structures: groups, rings and fields; used internally by pairing_t.

• a few miscellaneous functions, such as ones controlling how random bits are generated.
Functions operating on a given data type usually have the same prefix, e.g. those involving element_t objects begin with element_.

二,Tutorial (介紹)

This chapter walks through how one might implement the Boneh-Lynn-Shacham (BLS) signature scheme using the PBC library. It is based on the file example/bls.c.

We have three groups G1, G2, GT of prime order r, and a bilinear map e that takes an element from G1 and an element from G2, and outputs an element of GT. We publish these along with the system parameter g, which is a randomly chosen element of G2.

Alice wishes to sign a message. She generates her public and private keys as follows. Her private key is a random element x of Zr, and her corresponding public key is gxg^{x}.

To sign a message, Alice hashes the message to some element h of G1, and then outputs the signature hxh^x.

To verify a signature σ, Bob checks that e(h,gxg^x) = e(σ, g).

We now translate the above to C code using the PBC library.

【譯文】

本章介紹如何使用PBC庫實現Boneh-Lynn-Shacham(BLS)簽名方案。 它基於文件example / bls.c。(bls.c這個文件在pbc 庫中example目錄下)

我們有三組素數階爲r的羣G1,G2,GT,以及一個雙線性映射e,它需要一個G1的元素和一個G2的元素,然後輸出GT元素。 我們將它們與系統參數g一起發佈,系統參數g是從G2中隨機選擇的一個元素。

愛麗絲想要對一個消息簽名。 她按如下方式生成她的公鑰和私鑰。 她的私鑰是Zr(模r的剩餘環)中的一個隨機選取的元素x,而她對應的公鑰是 gxg^x

要簽名消息,Alice對消息做摘要生成G1的某個元素h,然後輸出簽名hxh^x

爲了驗證簽名σ,Bob檢查e(h,gxg^x)= e(σ,g)。

  • 註解:由雙線性對的運算性質可知:e(h,gxg^x)=e(hxh^x,g)=e(σ,g)

現在,我們使用PBC庫將以上內容轉換爲C代碼。

三,BLS Signature

First we include pbc/pbc.h:

#include <pbc.h>

Next we initialize a pairing:

pairing_t pairing;
char param[1024];
size_t count = fread(param, 1, 1024, stdin);
if (!count) pbc_die("input error");
pairing_init_set_buf(pairing, param, count);

Later we give pairing parameters to our program on standard input. Any file in the param subdirectory will suffice, for example:

$ bls < param/a.param

We shall need several element_t variables to hold the system parameters, keys and other quantities. We declare them and initialize them,

element_t g, h;
element_t public_key, secret_key;
element_t sig;
element_t temp1, temp2;

element_init_G2(g, pairing);
element_init_G2(public_key, pairing);
element_init_G1(h, pairing);
element_init_G1(sig, pairing);
element_init_GT(temp1, pairing);
element_init_GT(temp2, pairing);
element_init_Zr(secret_key, pairing);

generate system parameters,

element_random(g);

generate a private key,

element_random(secret_key);

and the corresponding public key.

element_pow_zn(public_key, g, secret_key);

When given a message to sign, we first compute its hash, using some standard hash algorithm. Many libraries can do this, and this operation does not involve pairings, so PBC does not provide functions for this step. For this example, and our message has already been hashed, possibly using another library.

Say the message hash is “ABCDEF” (a 48-bit hash). We map these bytes to an element h of G1,

element_from_hash(h, "ABCDEF", 6);

then sign it:

element_pow_zn(sig, h, secret_key);

To verify this signature, we compare the outputs of the pairing applied to the signature and system parameter, and the pairing applied to the message hash and public key. If the pairing outputs match then the signature is valid.

pairing_apply(temp1, sig, g, pairing);
pairing_apply(temp2, h, public_key, pairing);
if (!element_cmp(temp1, temp2)) {
    printf("signature verifies\n");
} else {
    printf("signature does not verify\n");
}
【譯文】

首先,我們要包含頭文件 pbc/pbc.h:

# include<pbc.h>

然後,初始化一個配對:

pairing_t pairing;
char param[1024];
size_t count=fread(param,1,1024,stdin);
if(!count)
  pbc_die("input error");
pairing_init_set_buf(pairing,param,count);

之後,我們從標準輸入獲得程序所需的配對參數;在param子目錄中的任何文件都能作爲標準輸入,比如:

$ bls < param/a.param

我們需要一些element_t類型的變量來保存這些系統參數、密鑰以及其他的量。我們要定義這些變量並且進行初始化。

element_t g,h;
element_t public_key,secret_key;
element_t sig;
element_t temp1,temp2; 

element_init_G2(g,pairing);
element_init_G2(public_key,pairing);
element_init_G1(h,pairing);
element_init_G1(sig,pairing);
element_init_GT(temp1,pairing);
element_init_GT(temp2,pairing);
element_init_Zr(secret_key,pairing);

然後產生系統參數g:

element_random(g);

生成公私鑰對:

element_random(secret_key);
element_pow_zn(public_key,g,secret_key);

如果對消息進行簽名,就要先使用SHA Hash算法計算消息的hash值。許多庫都有這個功能,因此PBC Library不再提供。在這個例子中,我們的消息大都已經使用其他庫做了摘要。

假設消息的摘要值是“ABCDEF”(一個48位的摘要值)。我們把這些字節映射爲G1的一個元素:

element_from_hash(h,"ABCDEF",6);

然後對他做簽名:

element_pow_zn(sig,h,secret_key);

配對作用於簽名和系統參數g的輸出爲輸出1,配對作用於消息摘要h和公鑰的輸出爲輸出2,我們可以比較輸出1和輸出2來驗證簽名的有效性。如果輸出1和2相匹配,則簽名有效。

pairing_apply(temp1,sig,g,pairing);
pairing_apply(temp2,h,public_key,pairing);
if(!element_cmp(temp1,temp2))
    printf("signature verifies\n");
else
	printf("signature does not verify\n");

四,Import/export

To be useful, at some stage the signature must be converted to bytes for storage or transmission:

int n = pairing_length_in_bytes_compressed_G1(pairing);
// Alternatively:
// int n = element_length_in_bytes_compressed(sig);
unsigned char *data = malloc(n);
element_to_bytes_compressed(data, sig);

On the other end, the signature must be decompressed:

element_from_bytes_compressed(sig, data);

Eliding _compressed in the above code will also work but the buffer data will be roughly twice as large.

We can save more space by using the x-coordinate of the signature only

int n = pairing_length_in_bytes_x_only_G1(pairing);
// Alternative:
//   int n = element_length_in_bytes_x_only(sig);
unsigned char *data = malloc(n);
element_to_bytes_compressed(data, sig);

but then there is a complication during verification since two different points have the same x-coordinate. One way to solve this problem is to guess one point and try to verify. If that fails, we try the other. It can be shown that the pairing outputs of the two points are inverses of each other, avoiding the need to compute a pairing the second time. (In fact, there are even better ways to handle this.)

int n = pairing_length_in_bytes_x_only_G1(pairing);
//int n = element_length_in_bytes_x_only(sig);
unsigned char *data = malloc(n);

element_to_bytes_x_only(data, sig);

element_from_bytes_x_only(sig, data)

pairing_apply(temp1, sig, g, pairing);
pairing_apply(temp2, h, public_key, pairing);

if (!element_cmp(temp1, temp2)) {
    printf("signature verifies on first guess\n");
} else {
    element_invert(temp1, temp1);
    if (!element_cmp(temp1, temp2)) {
        printf("signature verifies on second guess\n");
    } else {
        printf("signature does not verify\n");
    }
}
【譯文】

五,完整示例

1,編寫 bls.c文件

#include<pbc.h>
#include<stdio.h>
int main()
{
   pairing_t pairing;
   char param[1024];
   size_t count = fread(param, 1 , 1024 , stdin);
   printf("count=%lu\n",count);
   if (!count) 
     pbc_die("input error");
   pairing_init_set_buf(pairing, param, count);

   element_t g, h;
   element_t public_key, secret_key;
   element_t sig;
   element_t temp1, temp2;
   element_init_G2(g, pairing);
   element_init_G2(public_key, pairing);
   element_init_G1(h, pairing);
   element_init_G1(sig, pairing);
   element_init_GT(temp1, pairing);
   element_init_GT(temp2, pairing);
   element_init_Zr(secret_key, pairing);

   element_random(g);
   element_random(secret_key);
   element_pow_zn(public_key, g, secret_key);
   
   char *message="ABCDEF";
   element_from_hash(h, message, 6); 
   element_pow_zn(sig, h, secret_key);

   pairing_apply(temp1, sig, g, pairing);
   pairing_apply(temp2, h, public_key, pairing);
   if (!element_cmp(temp1, temp2)) {
       printf("signature verifies\n");
   } else {
       printf("signature does not verify\n");
   }   
   return 0;
}

2,在 Ubuntu 上進行編譯

$ gcc bls.c -lgmp -lpbc -I/home/book/pbc/pbc/include -o bls
// -l選項鍊接庫文件pbc,gmp
// -I選項指定頭文件pbc.h所在目錄/home/book/pbc/pbc/include

$ ./bls < /home/book/pbc/pbc/param/a.param  

3,運行結果

count=359
signature verifies
發佈了99 篇原創文章 · 獲贊 77 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章