Problemas com assinaturas digitais

7 respostas
E

Estou desenvolvendo um aplicativo que assina e verifica assinaturas de documentos utilizando uma chave privada e publica do algoritmo ElGamal (estou utilizando o provedor criado pelo autor do livro Java Cryptography). Sendo que o par de chaves é salvo em um arquivo .txt. A minha dúvida é, mesmo estando tudo certo, ALGUMAS vezes, o java lança uma ArithmeticException com a mensagem “BigInteger not invertible”, sendo que também informa que vem de uma fonte desconhecida (unknown source). Não é sempre que ocorre este erro, por isso eu estou achando bem estranho… Bom, gostaria que me ajudassem…

7 Respostas

louds

Você deve estar informando valores iniciais inválidos pro provedor.

Só por curiosidade, por que usar ElGamal, que apesar de ser tão seguro quando DSA ou RSA, é mais lento e dobra o tamanho da saida criptografada?

RSA é uma escolha muito mais segura dado que o problema de fatoração inteira é muito mais conhecido e estudado que o de logaritmo discreto.

E

Sim, mas no projeto utilizamos um algoritmo de derivação de chaves criptográficas utilizando o sistema ElGamal…

E

Aqui está o printStackTrace do erro:

java.lang.ArithmeticException: BigInteger not invertible.

at java.math.MutableBigInteger.modInverse(Unknown Source)

at java.math.MutableBigInteger.mutableModInverse(Unknown Source)

at java.math.BigInteger.modInverse(Unknown Source)

at java.math.BigInteger.modPow(Unknown Source)

at ecfv.compartilhamento.elgamal.ElGamalSignature.engineSign(ElGamalSignature.java:65)

at java.security.Signature$Delegate.engineSign(Unknown Source)

at java.security.Signature.sign(Unknown Source)

at ecfv.cliente.processamento.Processamento.realizaAssinatura(Processamento.java:239)

at ecfv.cliente.Cliente.assinaOffLine(Cliente.java:520)

at ecfv.cliente.Cliente.actionPerformed(Cliente.java:577)

at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)

at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(Unknown Source)

at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)

at javax.swing.DefaultButtonModel.setPressed(Unknown Source)

at javax.swing.AbstractButton.doClick(Unknown Source)

at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)

at javax.swing.plaf.basic.BasicMenuItemUI$MouseInputHandler.mouseReleased(Unknown Source)

at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)

at java.awt.Component.processMouseEvent(Unknown Source)

at java.awt.Component.processEvent(Unknown Source)

at java.awt.Container.processEvent(Unknown Source)

at java.awt.Component.dispatchEventImpl(Unknown Source)

at java.awt.Container.dispatchEventImpl(Unknown Source)

at java.awt.Component.dispatchEvent(Unknown Source)

at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)

at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)

at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)

at java.awt.Container.dispatchEventImpl(Unknown Source)

at java.awt.Component.dispatchEvent(Unknown Source)

at java.awt.EventQueue.dispatchEvent(Unknown Source)

at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.run(Unknown Source)

E aqui a linha onde ele acusa erro:

BigInteger b = top.multiply(
    k.modPow(kOne.negate(), pminusone)).mod(pminusone);

Esse erro ocorre apenas algumas poucas vezes… Poderiam me ajudar?

T

Bom, como você sabe como se usa o ElGamal, deve saber o suficiente de teoria dos números para descobrir porque é que o erro está sendo gerado pelas linhas “if f.isZero() throw new ArithmeticException” que constam do código da função abaixo (veja o arquivo src\java\math\MutableBigInteger.java em src.zip).
Algum dos parâmetros que você está usando pode ocasionar esse problema, mas não sei lhe dizer.

/**
     * Calculate the multiplicative inverse of this mod mod, where mod is odd.
     * This and mod are not changed by the calculation.
     *
     * This method implements an algorithm due to Richard Schroeppel, that uses
     * the same intermediate representation as Montgomery Reduction
     * ("Montgomery Form").  The algorithm is described in an unpublished
     * manuscript entitled "Fast Modular Reciprocals."
     */
    private MutableBigInteger modInverse(MutableBigInteger mod) {
        MutableBigInteger p = new MutableBigInteger(mod);
        MutableBigInteger f = new MutableBigInteger(this);
        MutableBigInteger g = new MutableBigInteger(p);
        SignedMutableBigInteger c = new SignedMutableBigInteger(1);
        SignedMutableBigInteger d = new SignedMutableBigInteger();
        MutableBigInteger temp = null;
        SignedMutableBigInteger sTemp = null;

        int k = 0;
        // Right shift f k times until odd, left shift d k times
        if (f.isEven()) {
            int trailingZeros = f.getLowestSetBit();
            f.rightShift(trailingZeros);
            d.leftShift(trailingZeros);
            k = trailingZeros;
        }
        
        // The Almost Inverse Algorithm
        while(!f.isOne()) { 
            // If gcd(f, g) != 1, number is not invertible modulo mod
            if (f.isZero())
                throw new ArithmeticException("BigInteger not invertible.");

            // If f < g exchange f, g and c, d
            if (f.compare(g) < 0) {
                temp = f; f = g; g = temp;
                sTemp = d; d = c; c = sTemp;
            }

            // If f == g (mod 4) 
            if (((f.value[f.offset + f.intLen - 1] ^
                 g.value[g.offset + g.intLen - 1]) & 3) == 0) {
                f.subtract(g);
                c.signedSubtract(d);
            } else { // If f != g (mod 4)
                f.add(g);
                c.signedAdd(d);
            }

            // Right shift f k times until odd, left shift d k times
            int trailingZeros = f.getLowestSetBit();
            f.rightShift(trailingZeros);
            d.leftShift(trailingZeros);
            k += trailingZeros;
        }

        while (c.sign < 0)
           c.signedAdd(p);

        return fixup(c, p, k);
    }
E

Sim, o problema é que há vezes em que eu passo os mesmos parâmetros idênticos e dá certo, outras vezes, ocorre este erro… acho isto muito estranho…

T

Você está gerando uma chave usando números aleatórios (e é por isso que está ocorrendo esse erro de vez em quando, certo? )
Talvez sua implementação requeira testar os números para que não ocorram determinados problemas (por exemplo, o número deve ser provavelmente primo, por exemplo. Você não deve usar qualquer número aleatório).

E

Acho que eu resolvi o erro, o problema estava que eu implementei um algoritmo de derivação de chaves criptográficas e neste algoritmo havia uma variavel chamada k, entao pus pra essa variavel ser a mesma que o k usado no processo de assinatura… Creio que ai estivesse gerando algum conflito, nunca mais vi o erro depois de corrigido… Também reparei que os k não precisam ser iguais para que as assinaturas sejam autenticadas com as chaves derivadas… Bom, valeu por tudo. :slight_smile:

Criado 12 de fevereiro de 2005
Ultima resposta 16 de fev. de 2005
Respostas 7
Participantes 3