0

ライセンス アプリケーションの公開/秘密キーを使用して生成されたキーのサイズを一致させることができません。公開鍵/秘密鍵を作成し、公開鍵でユーザーの電子メールアドレスに署名してライセンスを作成し、公開鍵、ライセンス、および電子メールアドレスを使用して、ライセンスが実際に秘密鍵を使用してエンコードされていることを確認する自己完結型の例を作成しました (明らかに、これはそうではありません)。通常、すべてが 1 つのクラスになります)。

これはすべて機能しますが、ライセンス キーの 16 進バージョンは 96 文字 (つまり、48 バイト/384 ビットを表す) であり、私が望んでいたよりも少し長くなっています (対照的に、公開/秘密キーの長さは問題ではなく、長いほど良いです) )。32 (64 hex chars) バイトまたはおそらく 16 バイト (32 hex chars) を生成するために何を使用できますか?これのセキュリティは合理的ですか?

キーを生成するために選択されたアルゴリズム間の相互作用を理解していないため、別のアルゴリズムを選択するのはやや難しい

KeyPairGenerator.getInstance("DSA");

および署名のアルゴリズム

Signature.getInstance("SHA/DSA");

どちらのリストも見つかりません。

キーサイズを指定する公開/秘密キーペアを生成するときのもう1つのポイント

keyGen.initialize(1024, new SecureRandom());

ただし、公開鍵 (443 バイト) も秘密鍵 (335 バイト) も、両方の合計 (778 バイト) も、この数値と一致しません。

import org.apache.commons.codec.binary.Hex;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 *
 */
public class CreateLicense
{

    private String PUBLIC_KEY;
    private String PRIVATE_KEY;

    public static void main(final String[] args)
    {
        try
        {
            String email = args[0];
            System.out.println("Creating license for:"+email);
            CreateLicense cl = new CreateLicense();
            cl.generatePublicPrivateKeyPair();
            String license = cl.createLicense(email);
            cl.checkLicense(email, license);

        }
        catch(Throwable t)
        {
            t.printStackTrace();
        }
    }

    //Would only be done once on server
    private void generatePublicPrivateKeyPair() throws Exception
    {
        final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
        keyGen.initialize(1024, new SecureRandom());
        final KeyPair pair = keyGen.generateKeyPair();
        PrivateKey privateKey = pair.getPrivate();
        PRIVATE_KEY=Hex.encodeHexString(privateKey.getEncoded());
        PublicKey  publicKey = pair.getPublic();
        PUBLIC_KEY=Hex.encodeHexString(publicKey.getEncoded());
        System.out.println("PrivateKeyHexLength:"+privateKey.getEncoded().length);
        System.out.println("PublicKeyHexLength:"+publicKey.getEncoded().length);

    }

    private PrivateKey reinflatePrivateKey(String keyAsHexString) throws Exception
    {
        byte[] keyBytes = Hex.decodeHex(keyAsHexString.toCharArray());
        final  PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        final  KeyFactory keyFactory = KeyFactory.getInstance("DSA");
        final  PrivateKey privateKey = keyFactory.generatePrivate(privKeySpec);
        return privateKey;
    }

    private PublicKey reinflatePublicKey(String keyAsHexString) throws Exception
    {
        byte[] keyBytes = Hex.decodeHex(keyAsHexString.toCharArray());
        final  X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyBytes);
        final  KeyFactory keyFactory = KeyFactory.getInstance("DSA");
        final  PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
        return publicKey;
    }

    //License Create on server based on email address
    private String createLicense(String emailAddress) throws Exception
    {
        String message=emailAddress;
        PrivateKey privateKey =  reinflatePrivateKey(PRIVATE_KEY);
        final Signature dsa = Signature.getInstance("SHA/DSA");
        dsa.initSign(privateKey);
        dsa.update(message.getBytes());
        final byte[] m1 = dsa.sign();
        String license =  Hex.encodeHexString(m1);
        System.out.println("CreateLicense:"+license+":Size:"+license.length());
        return license;
    }

    //Client checks that given known emailaddress and public key that a if a license was derived from
    //that and corresponding privatekey it would match license.
    private boolean checkLicense(String  emailAddress, String license) throws Exception
    {
        String message=emailAddress;
        PublicKey publicKey =  reinflatePublicKey(PUBLIC_KEY);
        final Signature dsa = Signature.getInstance("SHA/DSA");
        dsa.initVerify(publicKey);
        dsa.update(message.getBytes());

        boolean result = dsa.verify(Hex.decodeHex(license.toCharArray()));
        System.out.println("Result"+result);
        return result;
    }
}

のような出力を与える

Creating license for:testuser@nowhere.com
PrivateKeyHexLength:335
PublicKeyHexLength:443
CreateLicense:302c021425f7ad7289b073f82a1d808838f43e0134c5591402140d2a7a4e3967706d4659dc73ace6455040a5fc6b:Size:92
Resulttrue
4

1 に答える 1

0

@Paul - ここでの解決策は、ECDSA を使用することだと思います。コード行を変更する

final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");

final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA");

キーは DSA よりもはるかに短く、16 進バージョンの署名の方が短いと確信しています。たとえば、256 ビットまたは 128 ビットのプライム ECC 曲線を使用することをお勧めします。

これで問題が解決するかどうかお知らせください。

于 2013-02-26T15:07:31.817 に答える