【问题标题】:Error decoding signature bytes : "java.security.SignatureException: error decoding signature bytes"错误解码签名字节:“java.security.SignatureException:错误解码签名字节”
【发布时间】:2014-11-29 11:46:38
【问题描述】:

我在课堂上尝试验证 ECDSA 签名时遇到此错误。错误代码是:

java.security.SignatureException: error decoding signature bytes.
at org.bouncycastle.jcajce.provider.asymmetric.util.DSABase.engineVerify(Unknown Source)
at java.security.Signature$Delegate.engineVerify(Signature.java:1172)
at java.security.Signature.verify(Signature.java:623)
at SDSGeneration.Signing.verify_signature(Signing.java:88)
at com.sdsweb.modele.VerificationBox.checkSignature(VerificationBox.java:121)
at com.sdsweb.modele.VerificationBox.verifieur(VerificationBox.java:84)
at com.sdsweb.servlet.Authentification.doGet(Authentification.java:55)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)......

我在 VerificationBox.java 类中这样调用方法:

public Map<Integer, String> checkSignature(String data_digest, Signature SignObject, PublicKey publicKey, byte[] Signaturebyte) throws InvalidKeyException, SignatureException, NoSuchProviderException, NoSuchAlgorithmException{

    Map<Integer, String> erreur_signature = new HashMap<Integer, String>();

    Signing SignVerifier = new Signing();

    SignVerifier.setEcdsa_signature();

    SignVerifier.verify_signature(publicKey, SignVerifier.getEcdsa_signature(), data_digest, Signaturebyte);

    if (SignVerifier.getVerify_result()){
        erreur_signature.put(j, "SIGNATURE ÉRONNÉ, CODE SDS INVALIDE");
        j++;
    }
    return null;

}

这是 SDSGeneration.Signing 类:

package SDSGeneration;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.KeyPair;
import java.security.SignatureException;

//This class provide an instance of all object which are needed to sign data
public class Signing {

    public Signing() {

    }

    public Signing(KeyPair keygen) {

    }

    //ECDSA Signature Object
    private Signature ecdsa_signature;
    //KeyPair object
    private KeyPair keygen;
    //Final data signature
    private byte[] signature;
    //Boolean variable telling if the signing proccess was succesfful or not
    private Boolean verify_result;

    public Boolean getVerify_result() {
        return verify_result;
    }

    public byte[] getSignature() {
        return signature;
    }


    public KeyPair getKeygen() {
        return keygen;
    }

    public Signature getEcdsa_signature() {
        return ecdsa_signature;
    }

    public void setEcdsa_signature() throws NoSuchAlgorithmException, NoSuchProviderException {

        this.ecdsa_signature = java.security.Signature.getInstance("ECDSA", "BC");
    }

    public void setKeygen(KeyPair keygen) {
        this.keygen = keygen;
    }



    //This method is use to sign data. A call to a  sign  method resets the signature object to the state it was in when previously initialized for signing via a call to  initSign. 
    //That is, the object is reset and available to generate another signature with the same private key, if desired, via new calls to  update  and  sign .
    public void generate_signature(KeyPair keygen, Signature ecdsa_signature, String data) throws InvalidKeyException, SignatureException{

        //inserting private key in signature object
        ecdsa_signature.initSign(keygen.getPrivate());

        //inserting data to sign
        ecdsa_signature.update(data.getBytes());

        //signing
        this.signature = ecdsa_signature.sign();
    }

    //This method is use to sign data. A call to the  verify  method resets the signature object to its state when it was initialized for verification via a call to initVerify . 
    //That is, the object is reset and available to verify another signature from the identity whose public key was specified in the call to  initVerify .
    public void verify_signature(PublicKey keygen, Signature ecdsa_signature, String data, byte[] signature) throws InvalidKeyException, SignatureException{

        //generating the signature
        ecdsa_signature.initVerify(keygen);

        //inserting data to verify
        ecdsa_signature.update(data.getBytes());

        //verifying
        this.verify_result = ecdsa_signature.verify(signature);
    }
}

我编写了一个测试类来测试 SDSGeneration.Signing 代码和一切正常,签名和验证数据,但是在我的项目中导入和使用它时,出现以下错误。这是测试类代码:

    package SDSGeneration;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;

public class TestSigning {

    public TestSigning() {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, InvalidKeyException, SignatureException {
        // TODO Auto-generated method stub
        GenerateKeyPair new_keypair = new GenerateKeyPair();

        Signing testSign = new Signing();
        testSign.setKeygen(new_keypair.getKeygen());

        testSign.setEcdsa_signature();

        testSign.generate_signature(testSign.getKeygen(), testSign.getEcdsa_signature(), "Fanfe Yvon");

        testSign.verify_signature(testSign.getKeygen().getPublic(), testSign.getEcdsa_signature(), "Fanfe Yvon", testSign.getSignature());

        System.out.println("Signature result : " + testSign.getVerify_result() + " ; signature of data : " + testSign.getSignature());
    }

}

【问题讨论】:

  • 这个 SDSGeneration.Signing 类有什么作用?
  • SDSGeneration 签名类负责签名和验证签名。是包含 checkSignature() 方法的类,负责签名验证。
  • 您是否检查过(例如,使用 ASN.1 转储)该 ecdsa 签名是如何编码的?有不同的编码,可能您的 bc 版本不支持所有这些。
  • 没有输入、输出,当然还有示例键,就不可能有好的答案。我可以理解英语不是您的母语,但对于 Java,请遵守 Java code conventions(或代码约定的某些衍生语言)。
  • 好吧,你是对的。

标签: java eclipse security digital-signature ecdsa


【解决方案1】:

问题是我使用了错误的 CHARSET 将签名编码到存储中。

我必须先将其编码为 Base64 并在存储之前将其编码为 UTF-8,如下所示:

String signTostring = DatatypeConverter.printBase64Binary(signature);
signTostring = URLEncoder.encode(signTostring, "UTF-8");

如果我想使用它,我会执行反向操作以获取原始签名

String st = URLDecoder.decode(code.getSignature(), "UTF-8");
byte[] sign_byte = DatatypeConverter.parseBase64Binary(st); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 2015-04-13
    • 2013-05-21
    • 2012-03-06
    相关资源
    最近更新 更多