此问题是在继续过去的问题中生成的.如何RSA验证在php中生成的java中的签名.该代码适用于简单文本.但是现在我要求签署和验证格式中还有公钥(除验证密钥之外)的文本.
text1:text2:exported-public-key
示例:
53965C38-E950-231A-8417-074BD95744A4:22-434-565-54544:MIIBCgKCAQEAxWg6ErfkN3xu8rk9WsdzjL5GpjAucMmOAQNeZcgMBxN+VmU43EnvsDLSxUZD1e/cvfP2t2/dzhtV6N2IvT7hveuo/zm3+bUK6AnAfo6pM1Ho0z4WetoYOrHdOVNMMPaytXiVkNlXyeWRF6rl9JOe94mMYWRJzygntiD44+MXsB6agsvQmB1l8thg/8+QHNOBBU1yC4pLQwwO2cb1+oIl0svESkGpzHk8xJUl5jL6dDnhqp8+01KE7AGHwvufrsw9TfVSAPH73lwo3mBMVXE4sfXBzC0/YwZ/8pz13ToYiN88DoqzcfD3+dtrjmpoMpymAA5FBc5c6xhPRcrn24KaiwIDAQAB
PHP代码:
$rsa = new Crypt_RSA(); $keysize=2048; $pubformat = "CRYPT_RSA_PUBLIC_FORMAT_PKCS1"; $privformat = "CRYPT_RSA_PRIVATE_FORMAT_PKCS8"; $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8); $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); $d = $rsa->createKey($keysize); $Kp = $d['publickey']; $Ks = $d['privatekey']; $rsa = new Crypt_RSA(); $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8); $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); $d = $rsa->createKey($keysize); $Kver = $d['publickey']; $KSign = $d['privatekey']; $plainText = "53965C38-E950-231A-8417-074BD95744A4:22-434-565-54544:".$Kp; // Signing $hash = new Crypt_Hash('sha256'); $rsa = new Crypt_RSA(); $rsa->loadKey($KSign); $rsa->setSignatureMode(CRYPT_RSA_ENCRYPTION_PKCS1); $rsa->setHash('sha256'); $signature = $rsa->sign($plainText); $signedHS = base64_encode($signature); // Verification $signature = base64_decode($signedHS); $rsa->loadKey($Kver); $status = $rsa->verify($plainText, $signature); var_dump($status);
JAVA代码
import static java.nio.charset.StandardCharsets.UTF_8; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.spec.X509EncodedKeySpec; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.Security; import java.security.Signature; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; //import java.util.Base64; //import java.util.Base64.Decoder; import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class VerifySig { public static RSAPublicKey fromPKCS1Encoding(byte[] pkcs1EncodedPublicKey) { // --- parse public key --- org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey; try { pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey .getInstance(pkcs1EncodedPublicKey); } catch (Exception e) { throw new IllegalArgumentException( "Could not parse BER PKCS#1 public key structure", e); } // --- convert to JCE RSAPublicKey RSAPublicKeySpec spec = new RSAPublicKeySpec( pkcs1PublicKey.getModulus(), pkcs1PublicKey.getPublicExponent()); KeyFactory rsaKeyFact; try { rsaKeyFact = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("RSA KeyFactory should be available", e); } try { return (RSAPublicKey) rsaKeyFact.generatePublic(spec); } catch (InvalidKeySpecException e) { throw new IllegalArgumentException( "Invalid RSA public key, modulus and/or exponent invalid", e); } } public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); String pkey = "MIIBCgKCAQEA+8fKYCT4QiFUdsJ7VdF4xCkVmq/Kwc/10Jl3ie6mvn8hEsC3NAtMJu+Od12gyWYsS0zBDiQ8h2pGZ7p4uWqenc01dRRrq+g968zmoCKPUllPUuR6v9o+wYTX/os4hgaQSBg7DQn4g3BEekcvyk6e6zAMvuhHjeqnrinhCMFgJUhFL8zFNoyaH559C0TNbR6BTKzOoikah8cKhu4UOga0tWDC0I2Ifus/sHOwVaOBkDFIzD6jBxDH/QF8FsrLLTocuIb7Y6lVxFPPtgiUJku6b7wKExV0bPJvm6/Xhv1GX1FpMrA0Ylzj5IFviuviwgo534EcZQ/Hx3aIf4oPG8jVTQIDAQAB"; byte[] dpkey = Base64.decodeBase64(pkey); RSAPublicKey publicKey = fromPKCS1Encoding(dpkey); String plainData = "53965C38-E950-231A-8417-074BD95744A4:22-434-565-54544:MIIBCgKCAQEArszIunGg3ievJOpgesYQsp3nPGgrW+3VwkivkkktOXUBRzb3G3mZzidEjG6LxNe/rrNe0UczmnSHQoSBxJCHyUnCWNfScBD66CFG4hLo5Z1gxrP8D2M2lCa6ap2PWcsKiWqlu38EinMeBjBvB4aYpF7+FkFy64ObxR4pfVZxnxradkD0HvvMPLMbyeHxeGqYf8orERf9jfuKTdY8V44rxht2D2fg2WhB1+XL0JulsPvgOaSK3RPnwi+RQAJbihCIh5Zznn0KQCs5pIWoT3XKe1DMpQuEmphSOY9ZUg3AwlOrpRV+565x6GCSc615/6nowmqKzE4T7qT5nbH+ctiEHQIDAQAB"; String data = "iD96rNeR51BF2TUZSaw+QhW8SnsMXE5AdJiDVmJk6LL55jC26PBCnqXrFo2lsQt8aWRsZc0bHFGCcuIbhHA+Duo1/PwrxTqC5BZFL/frqsRSVa+vpvGEnj3xe4iImTEasMicQzzaAG9IWIgkRZ272lUZ8PqdtTuqAsRIwir6fEsfVs5uIErEWM18R4JxlFBc3LDIjFOFemEPSVIEBHwWht1c/CrdTtxPRIiugEb1jdofEBUNcWPZgfvApVx5+0aS9WTl31AY+RMlvp+13P/FQgAMnH9rvBdopRIVsZUNlMf8AOE2afhLPfOgx+41rzCB2wGCrRGELbml466WJ3wYNQ=="; byte[] ciphertext = Base64.decodeBase64(data); System.out.println(new String(plainData.getBytes(), UTF_8)); verifyBC(publicKey, plainData, ciphertext); System.out.flush(); } private static void verifyBC(PublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { // what should work (for PKCS#1 v1.5 signatures), requires Bouncy Castle provider //Signature sig = Signature.getInstance( "SHA256withRSAandMGF1"); Signature sig = Signature.getInstance( "SHA256withRSA"); sig.initVerify(publicKey); sig.update(plainData.getBytes(UTF_8)); System.out.println(sig.verify(ciphertext)); } }
它没有给出任何错误,只是在plainText中使用公钥时返回false.如果在使用公钥删除后尝试,它会工作并返回true.
PHP工作正常,签名在所有情况下都经过验证.
我怀疑java是否无法验证具有base 64 text/public key作为文本的数据?
更新:我比较了两次的二进制字节,结果显示出微小的差异.
第一个案例
PHP - > #C: sQ
JAVA - > /#C: sQ
第二个案例
PHP - > ]Q0l O+
JAVA - > ]Q0l
如果php base64与apache base 64不兼容?