2

Javaプログラミングを使用して標準実装のものを再利用せずに、楕円曲線デジタル署名アルゴリズム(ECDA)を実装しています。私のプログラムはこのようなものです。

     public BigInteger[] sign(){

    // signature generation here

        rs[0] = r;
         rs[1] = s;
        return rs;
      }

しかし、実装されている標準アルゴリズムのように、このようなバイト配列を返したいと思っています。

    public byte[] sign()
    {      
           // my signature generation here already done
            rs[0] = r;
            rs[1] = s;   
          // help me here what shall i do instead of returning array of two BigIntegers
    }  

デジタル署名の sign() メソッドが (r,s) 値を配列バイトに結合して、呼び出し元の本文を返す方法。本体の呼び出しで、署名を検証するために get (r,s) ペアを戻す必要があります。

         // something like this
            public boolean verify(byte[] sigbyte )
              {

                 rArr =  // help me here
                 sArr = // help me here
                r =new BigInteger(rArr);
                s = new BigInteger(sArr);

               // i have already done signature verification here

               }           
4

2 に答える 2

3

FIPS 186-3 は、ECDSA 署名を bytearray としてシリアル化する方法を指定していません。

私が知っているすべての API とプロトコルは、次の 2 つの異なる標準的な方法のいずれかを使用します。

1) r と s を n の長さ (G の次数) になるようにゼロ パディングし、それらを連結します。

byte[] rArr = toUnsignedByteArray(r);
byte[] sArr = toUnsignedByteArray(s);
int nLength = (n.bitLength()+7)/8;
byte[] res = new byte[2*nLength];
System.arraycopy(rArr, 0, res, nLength - rArr.length, rArr.length);
System.arraycopy(sArr, 0, res, 2* nLength - sArr.length, nLength);

toUnsignedByteArray次のようなものです:

byte[] toUnsignedByteArray(BigInteger bi){
  byte[] ba = bi.toByteArray();
  if(ba[0] != 0){
    return ba;
  }
  else
  {
    byte[] ba2 = new byte[ba.length - 1];
    System.arraycopy(ba, 1, ba2, 0, ba.length - 1);
    return ba2;
  }
}

2) 次の ASN.1 構造の DER エンコードを使用します。

ECDSASignature ::= SEQUENCE {
    r   INTEGER,
    s   INTEGER
}

n が最大で 487 ビットであると仮定します (より大きなキーをサポートする必要がある場合、長さのエンコードは多少複雑になります)。

byte[] rArr = r.toByteArray();
byte[] sArr = s.toByteArray();
byte[] res = new byte[6 + rArr.length + sArr.length];
res[0] = 0x30;
res[1] = 4 + rArr.length + sArr.length;
res[2] = 0x02;
res[3] = rArr.length;
System.arraycopy(rArr, 0, res, 4, rArr.length);
res[4+rArr.length] = 0x02;
res[5+rArr.length] = sArr.length;
System.arraycopy(sArr, 0, res, 6+rArr.length, sArr.length);

デコードするには、次のようにします (これは非常に基本的なエラー耐性のないデコードです)。

if(enc[0]!=0x30) return false; // bad encoding
if(enc[1]&0x80!=0) return false; // unsupported length encoding
if(enc[2]!=0x02) return false; // bad encoding
if(enc[3]&0x80!=0) return false; // unsupported length encoding
int rLength = enc[3];
byte[] rArr = new byte[rLength];
System.arraycopy(enc, 4, rArr, 0, rLength);
BigInteger r = new BigInteger(rArr);
if(enc[4+rLength]!=0x02) return false; // bad encoding
if(enc[5+rLength]&0x80!=0) return false; // unsupported length encoding
int sLength = enc[5+rLength];
byte[] sArr = new byte[sLength];
System.arraycopy(enc, 6+rLength, sArr, 0, sLength);
BigInteger s = new BigInteger(sArr);

2 番目のエンコーディングは、Java セキュリティ アーキテクチャで使用されます。

于 2012-06-07T05:55:08.927 に答える
1

FIPS 186-3 ドキュメントはアルゴリズムを指定していますが、より高いレベルのプロトコルでアルゴリズムを使用する方法については言及していません。署名をバイト配列にエンコードするために私が最もよく知っている標準はRFC 3279、具体的にはセクション 2.2.2 です。これはおそらく、デフォルトの Oracle プロバイダーで使用されるエンコード方法です。

于 2012-06-07T03:09:35.953 に答える