将Java加密方法转换为Php
我试图生成一条加密的消息发送到远程服务器,当我用Java做这件事时,我成功了,但当我用PHP做这件事时,我失败了。 我希望您能帮助我指出php版本中的错误。下面是我的代码的Java和php版本将Java加密方法转换为Php,java,php,encryption,phpseclib,Java,Php,Encryption,Phpseclib,我试图生成一条加密的消息发送到远程服务器,当我用Java做这件事时,我成功了,但当我用PHP做这件事时,我失败了。 我希望您能帮助我指出php版本中的错误。下面是我的代码的Java和php版本 private String encryptMessage() { String msg = ""; String message = "this is the message to send"; String modulus = "xxxxxxxxxxxxxxx";
private String encryptMessage() {
String msg = "";
String message = "this is the message to send";
String modulus = "xxxxxxxxxxxxxxx";
String exponent = "111";
Security.addProvider(new BouncyCastleProvider());
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(modulus, 16), new BigInteger(exponent, 16));
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(publicKeySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] messageDataBytes = cipher.doFinal(message.getBytes("UTF8"));
msg = Base64.getEncoder().encodeToString(messageDataBytes).replaceAll("\\r|\\n", "");
return msg;
}
失败的php版本
private function encryptMessage()
{
$message = "this is the message to send";
$modulus = "xxxxxxxxxxxxxxx";
$exponent = "111";
$rsa = new RSA();
$exponent = new BigInteger( $exponent, 16);
$modulus = new BigInteger($modulus, 16);
$rsa->loadKey(['n' => $modulus, 'e'=>$exponent]);
$rsa->setPublicKey();
$publicKey = $rsa->getPublicKey();
openssl_public_encrypt($message, $encryptedData, $publicKey);
return base64_encode($encryptedData);
}
对于Java,我使用的是Bouncy Castle库,而我使用的是phpseclib版本2库
谢谢
Java方法的结果:(2)2+SX3+2+SX3+2+SX3+3+XX3+3+XX3+3+XX3+3+3+JJ9+JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWRWXQH2FiMo0GUTB4+YB4+YS9dQ==
来自PHP的结果:
1.这个词的意思是:vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv4R8OVSXJ6QIEYFX9TJNQP9C1XA=== 我的解决方案由3个文件组成,以获得一个完整的测试环境,并在Java中进行完整的加密和解密 并且只在PHP中使用加密 我正在使用的测试环境是Java端11.0.6+8-b520.43(没有任何依赖项,例如Bouncy Castle) 在PHP端,PHP版本7.4.6、openssl版本:openssl 1.1.1g,2020年4月21日和phpseclib 2.0.27 GenerateKeysSo.java:在模数/指数表示中生成RSA私钥/公钥对。我使用不安全的512位keylength只是为了让字符串长度稍微短一点-在生产中,您应该使用最小2048位keylength
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
public class GenerateKeysSo {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
System.out.println("https://stackoverflow.com/questions/53947613/rsa-public-key-generated-in-java-is-not-valid-in-php");
System.out.println("Generate RSA keys");
System.out.println("java version: " + Runtime.version());
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
//kpGen.initialize(2048, new SecureRandom());
kpGen.initialize(512, new SecureRandom()); // don't use 512 bitlength as it is insecure !
KeyPair keyPair = kpGen.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
byte[] privateKeyEncoded = privateKey.getEncoded();
byte[] publicKeyEncoded = publicKey.getEncoded();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
BigInteger modulus = rsaPublicKey.getModulus();
BigInteger privateExponent = rsaPrivateKey.getPrivateExponent();
BigInteger publicKeyExponent = rsaPublicKey.getPublicExponent();
System.out.println("privateKey Base64: " + Base64.getEncoder().encodeToString(privateKeyEncoded));
System.out.println("publicKey Base64: " + Base64.getEncoder().encodeToString(publicKeyEncoded));
System.out.println("modulus : " + modulus);
System.out.println("privateExponent : " + privateExponent);
System.out.println("publicExponent : " + publicKeyExponent);
}
}
结果很短,您需要使用copy/paste将模数、privateExponent和publicExponent的3个值复制到EncryptSo.java和
EncryptSo.php:
Generate RSA keys
java version: 11.0.6+8-b520.43
privateKey Base64: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAgKpP+4e9D3r5Mbw4VBaQQG/LRw7nqDOWOU6p+teU2c+mTPE2apPzYUku9AaNf+BiPyjzmkWh/9d7E5jUDWfS9QIDAQABAkA9Ia5y0eFwE3uGt+kDetz64KLylhBXCHudqtR0TC169s4UfGr6EquaqX9YKmQ4ApC5mkO65Rha8V0WzV6PEUlBAiEA6XtDObkbbhAMaDXpLkzqu0I5O2e3cpTMGwCTaK/0GVkCIQCNExoakOZ1+0f5UuiztmGo7UqBpZEieiybL25H/iI2/QIhANPubzcWLy/YoWp2hRLh/q+7jPe/TWVUa3CXNTbxgEEBAiAyA22jsW8isJ0JlQ0OeUASJV3erJXRhUK/GYedWklC+QIgLnxzZVDSNNEGYFpUER0v2bIFWqVXlnm87y5LRbzWn/I=
publicKey Base64: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAICqT/uHvQ96+TG8OFQWkEBvy0cO56gzljlOqfrXlNnPpkzxNmqT82FJLvQGjX/gYj8o85pFof/XexOY1A1n0vUCAwEAAQ==
modulus : 6738747659637003090018178263545882875809887577706500222853194115214616163418986509701683514500084328991941041539147237736316411294805049495944982937719541
privateExponent : 3201720015041533823900789397901821886674218828976379815054133670438877551559197501362784700723343540531608097210070472157677675484894343978127401531033921
publicExponent : 65537
文件2是Java中的加密/解密例程(EncryptSo.Java)。将GenerateSo中的3个值粘贴到三个字符串变量moduleString,
privateExponentString和publicExponentString。运行该程序,它将对消息进行加密和解密。运行PHP加密后(文件3)
您在那里有一个输出-您可以将此输出粘贴到第42行(变量ciphertextFromPhp)。这个字符串也将被解密
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
public class EncryptSo {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException, IOException {
System.out.println("https://stackoverflow.com/questions/61966418/converting-a-java-encryption-method-to-php");
System.out.println("encrypt and decrypt with Java with key generation via modulus and exponent");
String modulusString = "7655411376708364139873444642436134423578239360576333940175884244078181837546293928220019721607335417517025652060442851820596480386882812189086919617782503";
String privateExponentString = "6181379361775076881056852519774102589787650800051550108278185489542231510128103539355646657479306697213227070361180012317478947328351699562861534356668225";
String publicExponentString = "65537";
BigInteger modulusBI = new BigInteger(modulusString);
BigInteger publicExponentBI = new BigInteger(publicExponentString,10); // 10 = numeric string
BigInteger privateExponentBI = new BigInteger(privateExponentString,10); // 16 = hex string
// generate private & public keys
KeyFactory factory = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulusBI, privateExponentBI);
PrivateKey privateKeyBI = factory.generatePrivate(rsaPrivateKeySpec);
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulusBI, publicExponentBI);
PublicKey publicKeyBI = factory.generatePublic(rsaPublicKeySpec);
// encryption
String message = "this is the message to send";
System.out.println("message Original : " + message);
String ciphertext = encryptMessageEnc(message, publicKeyBI);
System.out.println("message encrypted: " + ciphertext);
// decryption
String decryptedtext = decryptMessageEnc(ciphertext, privateKeyBI);
System.out.println("message decrypted: " + decryptedtext);
System.out.println("decryption of a encrypted message from PHP");
String ciphertextFromPhp = "B3a1v8oGVYqRpRwRwGP5KRaqaNiiXFRfTdWnz0LsI4Ek63BpXIrWsEXsVNaj1jSu4XIQNrvYHIpwdxwKQrBUUfXXwq6Pix0YfuOmz7mUJMyTerHMcVzcXIpEGAD/L0gGomfCbkahed/CimThPSO527ulazHVirOY173JjMTrWdqyFLS6L7sCD6UHkU49gW94ADkOJtRXOiIWTg==";
System.out.println("message encrypted: " + ciphertextFromPhp);
decryptedtext = decryptMessageEnc(ciphertext, privateKeyBI);
System.out.println("message decrypted: " + decryptedtext);
}
private static String encryptMessageEnc(String message, PublicKey publicKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException {
String msg = "";
//Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] ciphertextBytes = cipher.doFinal(message.getBytes("UTF8"));
msg = Base64.getEncoder().encodeToString(ciphertextBytes).replaceAll("\\r|\\n", "");
return msg;
}
private static String decryptMessageEnc(String msg, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
//Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] message = Base64.getDecoder().decode(msg);
byte[] messageDataBytes = cipher.doFinal(message);
return new String(messageDataBytes);
}
}
EncryptSo的输出:
encrypt and decrypt with Java with key generation via modulus and exponent
java version: 11.0.6+8-b520.43
message Original : this is the message to send
message encrypted: WZs0jp6yMWR71I4g7Oxo54A28yDZRBs5usKYLz9NfoRkMPy7vpe+riLSZzr6mdC8XZFNGveH9HsG2maZWSxhsw==
message decrypted: this is the message to send
decryption of a encrypted message from PHP
message encrypted: B3a1v8oGVYqRpRwRwGP5KRaqaNiiXFRfTdWnz0LsI4Ek63BpXIrWsEXsVNaj1jSu4XIQNrvYHIpwdxwKQrBUUfXXwq6Pix0YfuOmz7mUJMyTerHMcVzcXIpEGAD/L0gGomfCbkahed/CimThPSO527ulazHVirOY173JjMTrWdqyFLS6L7sCD6UHkU49gW94ADkOJtRXOiIWTg==
message decrypted: this is the message to send
文件3(EncryptSo.php)是一个简单的php应用程序,它通过模数和指数构建公钥,并且需要外部依赖项“phpseclib”。我只是手动包含了这个库,没有任何编写器帮助。将模数和指数粘贴到变量modulusString和publicExponentString,并让其运行
<?php
// https://stackoverflow.com/questions/61966418/converting-a-java-encryption-method-to-php
include('phpseclib\Math\BigInteger.php');
include('phpseclib\Crypt\RSA.php');
include('phpseclib\Crypt\HASH.php');
echo 'php version: ' . PHP_VERSION . ' openssl version: ' . OPENSSL_VERSION_TEXT . ' phpseclib 2.0.27' . PHP_EOL;
$message = "this is the message to send";
$modulusString = "7655411376708364139873444642436134423578239360576333940175884244078181837546293928220019721607335417517025652060442851820596480386882812189086919617782503";
$publicExponentString = "65537";
$rsa = new \phpseclib\Crypt\RSA();
//$rsa = new Crypt_RSA();
$exponent = new phpseclib\Math\BigInteger($publicExponentString, 256);
$modulus = new phpseclib\Math\BigInteger($modulusString, 256);
$PUBLICKEY = "";
$rsa->loadKey(['n' => $modulus, 'e'=>$exponent]);
$rsa->setPublicKey();
$publicKey = $rsa->getPublicKey();
openssl_public_encrypt($message, $encryptedData, $publicKey);
$encryptedData = base64_encode($encryptedData);
echo PHP_EOL ."encryptedData base64: " . $encryptedData . PHP_EOL;
// encryptedData base64: K4DCBvi2lWbyQJGiQbZ9cXiZy49sg+Q0KKPvj7+TMObTCyWKtoQce8pmUJlDZ48+K1Fy3vHtTTZFDQzr7fkWKoeYffl171IsxOgFLz2bmjQYhrNiLy5ZI03qUX4i9MI0mtSMlITXhiryDOajHB61Cgs5cfgH+yVCJItV7cM/qMBAGnQVqoMxRAKaSOBEz/zxp3If5X9Jb5zuhA==
?>
您需要向我们展示一个示例值和每个函数生成的输出,并指定哪个是正确的输出是什么让您认为Java方法是成功的,PHP是失败的?它们看起来都很成功。@PresidentJamesK.Polk结果被发送到服务器,其接受Java版本,而拒绝PHP版本。服务器是否提供了拒绝该版本的任何线索?可能是错误消息,或异常堆栈跟踪?不幸的是,它不是。它只是告诉我加密的数据有错误。
php version: 7.4.6 openssl version: OpenSSL 1.1.1g 21 Apr 2020 phpseclib 2.0.27
encryptedData base64: M5ys/5JrlleQO5MJDVl6FvRcIUIcxXQhp00y/KLHfB1p0XRNaVaWRwV9t5NKoJmo4wKI1KQI1H9PBd71c6t3i7IWsWcS8QsebOk5iitacvgOTJBW71pjrzWkv4+M7Ge8KZ/jhCl6nQ+e9zNSkJf4HZE1NHmOzFan3pBN1gXDptj19AZPue/MxqdAIgDD538UElvhTzyWMpCJeA==