В чем разница между вычислением подписи с помощью следующих двух методов?
- Вычислить подпись с помощью
Signature.getInstance("SHA256withRSA")
- Вычислить SHA256 с помощью
MessageDigest.getInstance("SHA-256")
и вычислить дайджест с помощьюSignature.getInstance("RSA");
, чтобы получить подпись?
Если они разные, существует ли способ изменить метод 2, чтобы оба метода дали один и тот же результат?
Я попробовал следующий код:
package mysha.mysha;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class MySHA256 {
public static void main(String[] args) throws Exception {
//compute SHA256 first
Security.addProvider(new BouncyCastleProvider());
String s = "1234";
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(s.getBytes());
byte[] outputDigest = messageDigest.digest();
//sign SHA256 with RSA
PrivateKey privateKey = Share.loadPk8("D:/key.pk8");
Signature rsaSignature = Signature.getInstance("RSA");
rsaSignature.initSign(privateKey);
rsaSignature.update(outputDigest);
byte[] signed = rsaSignature.sign();
System.out.println(bytesToHex(signed));
//compute SHA256withRSA as a single step
Signature rsaSha256Signature = Signature.getInstance("SHA256withRSA");
rsaSha256Signature.initSign(privateKey);
rsaSha256Signature.update(s.getBytes());
byte[] signed2 = rsaSha256Signature.sign();
System.out.println(bytesToHex(signed2));
}
public static String bytesToHex(byte[] bytes) {
final char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
Тем не менее, выходы не совпадают.
Ниже приведен пример вывода с моим тестовым ключом:
метод 1: 61427B2A2CF1902A4B15F80156AEB09D8096BA1271F89F1919C78B18D0BABA08AA043A0037934B5AE3FC0EB7702898AC5AE96517AFD93433DF540353BCCE72A470CFA4B765D5835E7EA77743F3C4A0ABB11414B0141EF7ECCD2D5285A69728D0D0709C2537D6A772418A928B0E168F81C99B538FD25BDA7496AE8E185AC46F39
метод 2: BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA
Обновление 1:
В соответствии с ответом mkl, я изменяю свой код, но все равно не могу понять. Я все еще что-то пропустил?
package mysha.mysha;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class MySHA256 {
public static void main(String[] args) throws Exception {
//compute SHA256 first
Security.addProvider(new BouncyCastleProvider());
String s = "1234";
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(s.getBytes());
byte[] outputDigest = messageDigest.digest();
AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, null);
DigestInfo di = new DigestInfo(sha256Aid, outputDigest);
//sign SHA256 with RSA
PrivateKey privateKey = Share.loadPk8("D:/key.pk8");
Signature rsaSignature = Signature.getInstance("RSA");
rsaSignature.initSign(privateKey);
rsaSignature.update(di.toASN1Primitive().getEncoded());
byte[] signed = rsaSignature.sign();
System.out.println("method 1: "+bytesToHex(signed));
//compute SHA256withRSA as a single step
Signature rsaSha256Signature = Signature.getInstance("SHA256withRSA");
rsaSha256Signature.initSign(privateKey);
rsaSha256Signature.update(s.getBytes());
byte[] signed2 = rsaSha256Signature.sign();
System.out.println("method 2: "+bytesToHex(signed2));
}
public static String bytesToHex(byte[] bytes) {
final char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
метод 1:
675D868546777C5A9B5E74988E0CD41A46A929C1D0890B32B1FBE34F12D68F1FDB56E623294DB903F6AC60A2ADA61976B27C66056A16F5790A78168803AD2C685F9B4CF983C939305A9819CBA9D95441CD7214D40D06A98B4DDF9692A7D300DD51E808A6722A0D7C288DBD476DF4DEEBB3DAF41CFC0978F24424960F86F0284E
метод 2:
BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA