2

CAVP プログラムからのテスト ベクトルを使用して、Sun JCE を使用して署名検証をコーディングしようとしています。

公開鍵の指数、係数、およびメッセージと署名が与えられます。私は次のことを行います:

    private static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes, int saltlen)  throws Exception
    {
            Signature sig = Signature.getInstance(algo);
            KeyFactory keyMaker = KeyFactory.getInstance("RSA");
            RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
                            new BigInteger(modulus),
                            new BigInteger(exponent));

            RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);

            System.out.println("algorithm is " + algo);
            sig.initVerify(pubKey);
            Utils.outputValue("n", modulus, modulus.length, System.out, false);
            Utils.outputValue("e", exponent, exponent.length, System.out, false);
            Utils.outputValue("Msg", message, message.length, System.out, false);
            Utils.outputValue("S", sigBytes, sigBytes.length, System.out, false);
            BigInteger Nvalue = pubKey.getPublicExponent();
            Utils.outputValue("key value of n", Nvalue.toByteArray(), System.out, false);
            BigInteger Evalue=pubKey.getModulus();
            Utils.outputValue("key value of e", Evalue.toByteArray(), System.out, false);
            sig.update(message);
            if(sig.verify(sigBytes))
                    oPS.println("Result = P");
            else
                    oPS.println("Result = F");

. . .

アルゴは「SHA1withRSA」のようなもので、示されているように公開鍵を作成します。キー自体から得られたモジュラスと指数をリストすると、それらは逆になっています。

n = 009de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003 Msg = 64b13df4b008ccccd5ce146018481c2568bbe2b93ec658d1c7f4ad734592cd65b3be2be5a7c1be9a7d9f49cbb2ece0cf8ee0a8c406aede84e0121bd51829d6e083862ae5b282d92c19d3923f70616f565a55c2134572116f91a85ff5f4e6ad2e1d31c15c97f3266af19574241c4fd2a4143fb80cc2b9fa7b22df0239a1715c35 S =5b4458f6aeff91c4699ee9bdf8757987fb8db229814a2992945ac53bcf19b9179e53cfed258726d205107ac000d41e570fe8c4fb321fc9b4b5469c60cd20032195f314ba6e6b0b30a51c9834242daa1ce525ec90380106568e782ea164baeda5d884defe6e720e9dd63618b823412445e17f991a6daa21bd62bdc73d7d8a20e5 key value of n = 03 key value of e = 009de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f009de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f009de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f

これらのテストの一部は失敗するはずですが、一部は成功するはずです。どれも正しく検証されていません...何か考えはありますか?ありがとう。

アプリケーションは以下のとおりで、その後に 1 セットのサンプル入力が続きます。

package cavp.rsa;


import cavp.*;

import java.io.*;

import java.security.KeyFactory;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.security.PublicKey;

import java.util.Date;

import java.math.BigInteger;

public class RSASigVerify
{
        private static boolean verboseFlag=false;

        public static void main(String[] args) throws Exception
        {
                String requestFile;
                String responseFile;

                int saltLen=-1;
                int argstart=0;

                if(args.length < 2)
                        throw new Exception("missing parameters");
                if(args.length == 3) {
                        if(args[0].equals("-saltlen")) {
                                saltLen=Integer.parseInt(args[1]);
                                if(saltLen < 0)
                                        throw new Exception("bad -saltlen parameter ");
                                argstart=2;
                        } else {
                                if(args[0].equals("-x931")) {
                                        saltLen=-2;
                                        argstart=1;
                                }
                } else {
                        if(args.length > 3)
                                throw new Exception("invalid invocation");
                }
                requestFile=args[argstart];
                responseFile=args[argstart+1];
                if(processFile(requestFile, responseFile, saltLen))
                        System.out.println("Failed to process file " + requestFile);
                else
                        System.out.println("Processing complete for " + requestFile);
        }

        private static boolean processFile(String rqfn, String rspfn, int saltLen) throws Exception
        {
                File inFile = new File(rqfn), outFile = new File(rspfn);

                if(!inFile.exists() || !inFile.isFile() || !inFile.canRead()) {
                        System.out.println("Bad input File " + rqfn);
                        return true;
                }
                FileReader inFR = new FileReader(inFile);
                BufferedReader inBR = new BufferedReader(inFR);
                PrintStream outPS = new PrintStream(outFile);

                String input, keyword, value, digestType=null;
                int p, v, q, i, lnum=0;
                byte[] Msg=null, nBytes=null, eBytes=null, sigBytes=null;
                boolean msgFound=false, nFound=false, eFound=false, sigFound=false;


                try {
                        while((input = inBR.readLine()) != null ) {
                                lnum++;
                                if((p = input.indexOf('=')) < 0) {
                                        outPS.println(input);
                                        continue;
                                }
                                if(input.charAt(p-1) == ' ')
                                        keyword=input.substring(0,p-1);
                                else
                                        keyword=input.substring(0, p);
                                p++;
                                for(i=p; i<input.length(); i++) {
                                        if(input.charAt(i) == ' ')
                                                p++;
                                        else
                                                break;
                                }
                                if((v = input.indexOf('\n')) > 0) {
                                        for(q=v-1; q>p+1; q--) {
                                                if(input.charAt(q) != ' ')
                                                        break;
                                        }
                                } else {
                                        if((v = input.indexOf(' ', p)) > 0) {
                                                q=v-1;
                                        } else {
                                                q=input.length();
                                        }
                                }

                                value=input.substring(p,q);
                                if(keyword.indexOf("n") >= 0) {
                                        nBytes=Utils.hexStringToByteArray(value);
                                        if(nBytes.length <= 0) {
                                                System.out.println("bad value for modulus");
                                                return true;
                                        }
                                        nFound=true;
                                } else {
                                        if(keyword.equals("e")) {
                                                eBytes=Utils.hexStringToByteArray(value);
                                                if(eBytes.length <= 0) {
                                                        System.out.println("bad value for private exponent");
                                                        return true;
                                                }
                                                eFound=true;

                                        } else {
                                                if(keyword.equals("SHAAlg")) {
                                                        if(!value.equals("SHA1") && !value.equals("SHA224") && !value.equals("SHA256") && !value.equals("SHA384") &&
                                                                        !value.equals("SHA512")) {
                                                                System.out.println("Bad SHAAlg parameter " + input);
                                                                return true;
                                                        }
                                                        digestType=value + "withRSA";
                                                } else {
                                                        if(keyword.equals("Msg")) {
                                                                if(msgFound) {
                                                                        System.out.println("more than one Msg found");
                                                                        return true;
                                                                } else
                                                                        msgFound=true;
                                                                String tempMsg;
                                                                if((value.length() & 0x01) != 0)  {
                                                                        tempMsg="0" + value;
                                                                } else {
                                                                        tempMsg=value;
                                                                }
                                                                Msg=Utils.hexStringToByteArray(tempMsg);
                                                                if(Msg.length <= 0) {
                                                                        System.out.println("bad Msg parameter");
                                                                        return true;
                                                                }
                                                        } else {
                                                                if(keyword.equals("S")) {
                                                                        sigBytes=Utils.hexStringToByteArray(value);
                                                                        if(sigBytes.length <= 0) {
                                                                                System.out.println("bad signature parameter");
                                                                                return true;
                                                                        }
                                                                        sigFound=true;
                                                                } else {
                                                                        if(keyword.equals("Result")) {
                                                                                continue;
                                                                        }
                                                                }
                                                        }
                                                }


                                        }
                                }
                                outPS.println(input);
                                if(digestType != null && msgFound && nFound && eFound && sigFound) {
                                        if(verifySignature(digestType, outPS, Msg, nBytes, eBytes, sigBytes, saltLen)) {
                                                throw new Exception("error in digest generator");
                                        }
                                        msgFound=false;
                                        eFound=false;
                                        sigFound=false;
                                }
                        }
                } catch( FileNotFoundException e) {
                        System.out.println("error processing file");
                }
                inFR.close();
                outPS.close();
                return false;
        }

        private static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes, int saltlen)  throws Exception
        {
                // yet to implement saltLen == -2 for X9.31 padding
                //                  saltLen >= 0 for PSS Signatures

                Signature sig = Signature.getInstance(algo);
                KeyFactory keyMaker = KeyFactory.getInstance("RSA");
                RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
                                new BigInteger(modulus),
                                new BigInteger(exponent));


                RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);

                System.out.println("algorithm is " + algo);
                sig.initVerify(pubKey);
                sig.update(message);
                if(sig.verify(sigBytes))
                        oPS.println("Result = P");
                else
                        oPS.println("Result = F");
                return false;
        }
}

以下は、入力からの 1 つのベクトルです。

# CAVS 11.5
# "SigVer PKCS#1 Ver 1.5" information for
# Mod sizes selected: 1024 2048
# SHA Algorithm selected:SHA1 SHA256
# Generated on Mon Nov 28 14:03:58 2011
[mod = 1024]
n = 9de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d>51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141>828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f
SHAAlg = SHA1
e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>0000000000000000000000000000000000000000000000000000000000000000000000000003
Msg = 64b13df4b008ccccd5ce146018481c2568bbe2b93ec658d1c7f4ad734592cd65b3be2be5a7c1be9a7d9f49cbb2>ece0cf8ee0a8c406aede84e0121bd51829d6e083862ae5b282d92c19d3923f70616f565a55c2134572116f91a8>5ff5f4e6ad2e1d31c15c97f3266af19574241c4fd2a4143fb80cc2b9fa7b22df0239a1715c35
S = 5b4458f6aeff91c4699ee9bdf8757987fb8db229814a2992945ac53bcf19b9179e53cfed258726d205107ac000>d41e570fe8c4fb321fc9b4b5469c60cd20032195f314ba6e6b0b30a51c9834242daa1ce525ec90380106568e78>2ea164baeda5d884defe6e720e9dd63618b823412445e17f991a6daa21bd62bdc73d7d8a20e5*

合格するベクターファイルは次のとおりです。

# CAVS 11.5
# "SigVer PKCS#1 Ver 1.5" information for 
# Mod sizes selected: 1024 2048
# SHA Algorithm selected:SHA1 SHA256
# Generated on Mon Nov 28 14:03:58 2011

[mod = 1024]

n = 9de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f

SHAAlg = SHA1
e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
Msg = fe196459e8232a9f94e8c93d88ddae7d38be7a10e2dd03ffb7bb9be43bd59659eec006b12c78c9e652f6c6d3220073a369459b8adea95eb34ede7979f634c7d931b208275365e201d4f82582b18553b70fab605721e1b6ae4d097cdb8a49183b0d16f22524917bd862176fb1fc1357a2731751df732c13dafc662e72bfbb9067
S = 94af4ce7f323d1bf4904a673d2884e30a55a108c44e4eb2bfc0a0f061f46fefe23fe74c760e947bd1fbf1bb1a30d66b3d7dccfb425d3a6551dd444f90d4f06c3e0da6dc3c7a45e062b08d24553f0091acae47ffaae495e13da66308dd9e0be87e2b960ab823f83e55815b66a1076ab238cc3883cbf7312521d0988214bb07d96
4

2 に答える 2

3

回答を更新しました。署名がメッセージと同じ長さであるため、サンプルが機能しないと言ったとき、私は正しくありませんでした。実際、RSA暗号化はSHA-1の計算後に行われるため、最終的な署名の長さは最大nバイトになる可能性があります。ここで、nはモジュラスのサイズですN

ですから、私が言えることから、あなたはまったく問題がないかもしれません。あなたが投稿したサンプルがポジティブなケースであると確信していますか?もしそうなら、それはSHA1withRSAアルゴリズムを使用して作成されたと確信していますか?

以下に、サンプル、Groovy、コードに基づくコードを含めました。コードは基本的に署名を作成し、それを検証します。このサイトから公開鍵と秘密鍵のペアを入手しましたが、どの鍵ペアでも機能します。コードは自明であるため、ランダムなキーペアとメッセージを使用してテストおよび検証する場合に、署名がどのように機能するかを要約します。

  1. メッセージmのハッシュコードhを計算します。この場合はです。h = SHA-1(m)
  2. 秘密鍵dを使用して署名/暗号化することにより、ハッシュコードhの署名sを計算します。
  3. 公開鍵eを使用して署名を検証/復号化し、値がmのハッシュコードと等しいことを確認して、署名sを検証します。

ご覧のとおり、上記の手順は単純なRSA計算ツールを使用して実行できます。コードで提供されている例が正しいことを確認しました。私が興味深いと思っjavax.crypto.BadPaddingException: Message is larger than modulusたのは、モジュラスが負の場合(1番目のビットが2の補数に設定されている場合)、Javaが例外をスローするため、左側に1バイトのゼロを追加する必要があったことです。

import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;


byte[] modulus = Utils.getBytes("00d94d889e88853dd89769a18015a0a2e6bf82bf356fe14f251fb4f5e2df0d9f9a94a68a30c428b39e3362fb3779a497eceaea37100f264d7fb9fb1a97fbf621133de55fdcb9b1ad0d7a31b379216d79252f5c527b9bc63d83d4ecf4d1d45cbf843e8474babc655e9bb6799cba77a47eafa838296474afc24beb9c825b73ebf549");
byte[] publicExp = Utils.getBytes("010001");
byte[] privateExp = Utils.getBytes("047b9cfde843176b88741d68cf096952e950813151058ce46f2b048791a26e507a1095793c12bae1e09d82213ad9326928cf7c2350acb19c98f19d32d577d666cd7bb8b2b5ba629d25ccf72a5ceb8a8da038906c84dcdb1fe677dffb2c029fd8926318eede1b58272af22bda5c5232be066839398e42f5352df58848adad11a1");
byte[] message = Utils.getBytes("00");
byte[] signature;
signature = createSignature("SHA1withRSA", System.out, message, modulus, privateExp, signature);
println ((new BigInteger(signature)).toString(16));
            verifySignature("SHA1withRSA", System.out, message, modulus, publicExp, signature);


public static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes)  throws Exception
{
    Signature sig = Signature.getInstance(algo);
    KeyFactory keyMaker = KeyFactory.getInstance("RSA");
    RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
    RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);

    sig.initVerify(pubKey);
    sig.update(message);

    return sig.verify(sigBytes);
}

public static byte[] createSignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes)  throws Exception
{
    Signature sig = Signature.getInstance(algo);
    KeyFactory keyMaker = KeyFactory.getInstance("RSA");
    RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(exponent));
    RSAPrivateKey privKey = (RSAPrivateKey)keyMaker.generatePrivate(privKeySpec);

    sig.initSign(privKey);
    sig.update(message);

    return sig.sign();
}

class Utils{
    private static char[] lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
    public static void outputValue(String s, byte[] data, int length, PrintStream out, boolean wtf){
        out.print(s+" = ");
        for(int i=0;i<length;i++){
            out.print(lookup[(data[i] >> 4) & 0xF]);
            out.print(lookup[data[i] & 0xF]);
        }
        out.println();
    }
    public static byte[] getBytes(String s){
        byte[] result = new byte[s.length()>>1];
        for(int i=0;i<result.length;i++){
            result[i] = Integer.parseInt(s.substring(i*2, i*2+2), 16);
        }
        return result;
    }
}
于 2012-06-26T06:44:03.550 に答える
0

あなたのコードは言う:

BigInteger Nvalue = pubKey.getPublicExponent();

N は、公開指数ではなく、キー係数です。テキスト ラベルと変数の内容が一致しません。

署名検証の問題は、おそらく別のものです。エラー メッセージが表示されますか、それともverify()単にメソッドが を返しfalseますか?

于 2012-06-26T05:13:45.607 に答える