使用Signature.sign签名Java String:为什么签名每次都不同?

时间:2016-09-08 21:18:47

标签: java sign

我编写了一个类,用于在服务器上使用私钥对一个文本字符串进行签名和base64,然后返回签名。每次为同一文本运行时,它都会生成不同的签名。为什么会这样做? 我已经通过在我的测试计算机上临时禁用转换来检查它是正在更改的签名而不是base64转换的问题。

我的代码:

public class SigningPIP implements SigningPIPInterface {
private static final String SIGNING_ALGORITHM = "SHA1withDSA";

/**
 * Provides a signature for a stringified JSON license
 * @param license stringified JSON license to be used for signature generation
 * @param keystoreFilePath The file path where the keystore can be found
 * @param keystorePassword The password to the keystore
 * @param privateKeyAlias The alias of the private key in the keystore to be used for signing
 * @param privateKeyPassword The password for the private key to be used for signing
 * @return Properties object containing the base64 encoded signature, algorithm used and certificate DN
 */
@Override
public Properties getLicenseSignature(String license, String keystoreFilePath, String keystorePassword, String privateKeyAlias, String privateKeyPassword) {
    PrivateKey privateKey = getPrivateKey(keystoreFilePath, keystorePassword, privateKeyAlias, privateKeyPassword);

    Properties licenseSignature = new Properties();
    licenseSignature.setProperty("sig_algorithm", SIGNING_ALGORITHM);
    licenseSignature.setProperty("cert_DN", getCertificateIssuerDN(keystoreFilePath, keystorePassword, privateKeyAlias));

    byte[] licenseByteArray = license.getBytes();
    System.out.println(new String(licenseByteArray));
    try {
        Signature dsa = Signature.getInstance(SIGNING_ALGORITHM);
        dsa.initSign(privateKey);
        dsa.update(licenseByteArray);
        byte[] signature = dsa.sign();
        licenseSignature.setProperty("signature_base64", DatatypeConverter.printBase64Binary(signature));
    }
    catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
        //TODO: Add logging
    }
    return licenseSignature;
}

/**
 * Pulls the private key from the specified keystore
 * @param keystoreFilePath The file path where the keystore can be found
 * @param keystorePassword The password to the keystore
 * @param privateKeyAlias The alias of the private key in the keystore
 * @param privateKeyPassword The password for the private key in the keystore
 * @return The specified private key from the keystore
 */
private PrivateKey getPrivateKey(String keystoreFilePath, String keystorePassword, String privateKeyAlias, String privateKeyPassword) {
    try {
        FileInputStream keyStoreFile = new FileInputStream(keystoreFilePath);
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(keyStoreFile, keystorePassword.toCharArray());
        return (PrivateKey)keyStore.getKey(privateKeyAlias, privateKeyPassword.toCharArray());
    }
    catch(KeyStoreException | NoSuchAlgorithmException | IOException | CertificateException | UnrecoverableKeyException e) {
        //TODO: Add logging;
    }
    return null;
}

/**
 * Pulls the Issuer DN from a keystore for the specified private key
 * @param keystoreFilePath The file path where the keystore can be found
 * @param keystorePassword The password to the keystore
 * @param privateKeyAlias The alias of the private key in the keystore
 * @return The Issuer DN for the private key
 */
private String getCertificateIssuerDN(String keystoreFilePath, String keystorePassword, String privateKeyAlias) {
    try {
        FileInputStream keyStoreFile = new FileInputStream(keystoreFilePath);
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(keyStoreFile, keystorePassword.toCharArray());
        X509Certificate certificate = (X509Certificate)keyStore.getCertificate(privateKeyAlias);
        return certificate.getIssuerDN().getName();
    } catch (IOException | NoSuchAlgorithmException | CertificateException | KeyStoreException e) {
        //TODO: Add logging
    }
    return null;
}

}

1 个答案:

答案 0 :(得分:1)

查看wikipedia article我猜它是因为它实现了RFC 6979,

  

这确保了每个H(m)的k是不同的,并且对于不知道私钥x的攻击者来说是不可预测的。

这是为了防止对密钥的攻击。