将公钥/私钥从一种编程语言迁移到另一种编程语言,用于签名有效负载并验证它们



我有一个Perl脚本,用私钥(id_rsa)签署有效负载,在linux机器上使用SSH-Keygen或OpenSSL生成。之后,我将获取哈希值或带符号值,以64进制解码并发送给我的scala代码。这里我发送了两个东西,公钥(id_rsa.pub)和编码的签名。

现在当我验证签名时,它总是给我错误的结果。我试过相反的方法,比如用Scala唱歌,用Perl验证。它给了我虚假的答复。我用Scala生成密钥并将其放入Linux中,然后用Perl完成签名和验证部分。它工作。当我在scala中导入两个密钥并尝试从scala中进行签名和验证部分时,它甚至可以工作。

但是每当我把这两者混在一起,比如在Perl中签名和在Scala中验证,或者在Scala中签名和在Perl中验证,它就会给我一个错误的结果。

我的问题是,这里是否有我可以使用的通用格式?我使用的代码是-

val fileOpened = Source.fromFile("file.hash") // taking the hashed value
val payload = fileOpened.getLines.mkString //file contents as string
val decodedString = Base64.getDecoder.decode(payload.getBytes) // Base64 Decoding of the hashed value
println("decodedString, the hash value was base64 encoded, so decoded it and took into bytes")
println(decodedString) //the hash value was base64 encoded, so decoded it and took into bytes
val fileOpened1 = Source.fromFile("file")
val ComareElement = fileOpened1.getLines.mkString
val decodedString1 = new String(ComareElement).getBytes
println("decodedString1,  this is the main payload to compare, turned into bytes")
println(decodedString1) // this is the main payload to compare, turned into bytes
//val keyPairGen = KeyPairGenerator.getInstance("RSA") //Creating KeyPair generator object
//keyPairGen.initialize(2048, new SecureRandom) //Initializing the key pair generator
//val pair: KeyPair = keyPairGen.generateKeyPair
// save public key as id_rsa.pub
//val x509keySpec = new X509EncodedKeySpec(pair.getPublic.getEncoded)
//val publicKeyStream = new FileOutputStream("C:\MyWorkSpace\PayLoadSign\src\main\scala\id_rsa.pub")
//publicKeyStream.write(x509keySpec.getEncoded)
// save private key as id_rsa
//val pkcs8KeySpec = new PKCS8EncodedKeySpec(pair.getPrivate.getEncoded)
//val privateKeyStream = new FileOutputStream("id_rsa")
//privateKeyStream.write(pkcs8KeySpec.getEncoded)
val filePublicKey = new File("id_rsa.pub")
var inputStream = new FileInputStream("id_rsa.pub")
val encodedPublicKey: Array[Byte] = new Array[Byte](filePublicKey.length.toInt)
inputStream.read(encodedPublicKey)
inputStream.close()
val filePrivateKey = new File("id_rsa")
inputStream = new FileInputStream("id_rsa")
val encodedPrivateKey: Array[Byte] = new Array[Byte](filePrivateKey.length.toInt)
println("The key is now " +encodedPrivateKey)
inputStream.read(encodedPrivateKey)
inputStream.close()
val keyFactory: KeyFactory = KeyFactory.getInstance("RSA")
// public key
val publicKeySpec: X509EncodedKeySpec = new X509EncodedKeySpec(encodedPublicKey)
val publicKey: PublicKey = keyFactory.generatePublic(publicKeySpec)
// private key
val privateKeySpec: PKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey)
val privateKey: PrivateKey = keyFactory.generatePrivate(privateKeySpec)
new KeyPair(publicKey, privateKey)
// val pair = keyPairGen.generateKeyPair //Generate the pair of keys
//val privKey = pair.getPrivate //Getting the privatekey from the key pair
//val pubKey = pair.getPublic  //Getting the PublicKey from the key pair
val privKey = privateKey //Getting the privatekey from the key pair
val pubKey = publicKey  //Getting the PublicKey from the key pair
println("Getting the privateKey from the key pair " + privateKey)
println("Getting the publicKey from the key pair " + publicKey)
var writer = new PrintWriter(new File("C:\MyWorkSpace\PayLoadSign\src\main\scala\Private_Key"))
writer.write(privKey.toString)
writer.close()
writer = new PrintWriter(new File("C:\MyWorkSpace\PayLoadSign\src\main\scala\Public_Key"))
writer.write(pubKey.toString)
writer.close()
val sign = Signature.getInstance("SHA256withRSA") //Creating a Signature object
//sign.initSign(privKey)
//val bytes = payload.getBytes //Initializing the signature
val bytes = decodedString
println(bytes)
//sign.update(bytes) //Adding data to the signature
//val signature = sign.sign //Calculating the signature
//val signedPayload = new BASE64Encoder().encode(signature)
//writer = new PrintWriter(new File("file.hash"))
//writer.write(signedPayload)
//writer.close()
println(bytes)
sign.initVerify(pubKey)  //Initializing the signature
sign.update(bytes)
//println(signature)
//val bool = sign.verify(new BASE64Decoder().decodeBuffer(signedPayload)) //Verifying the signature
//println(sign.verify(signature))
val bool = sign.verify(bytes)
println(bool)
if (bool) System.out.println("Signature verified")
else System.out.println("Signature failed")
}

我找到了一个解决方案。我通过在Perl中纠正签名算法及其默认值实现了这一点。此外,您还必须注意新的行字符(n)。修改后的验证代码在Scala中应该如下所示-

object Verify_Test extends App {

var privateKeyString = new String(Files.readAllBytes(Paths.get("private_key.pem")), Charset.defaultCharset)
privateKeyString = privateKeyString.replaceAll("\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "")
var publicKeyString = new String(Files.readAllBytes(Paths.get("public_key.pem")), Charset.defaultCharset)
publicKeyString = publicKeyString.replaceAll("\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "")
val keyFactory = KeyFactory.getInstance("RSA")
val encodedPrivateKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString))
val privateKey = keyFactory.generatePrivate(encodedPrivateKeySpec)
val encodedPublicKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString))
val publicKey = keyFactory.generatePublic(encodedPublicKeySpec)
var encodedSignatureVale = new String(Files.readAllBytes(Paths.get("hashedSignature")), Charset.defaultCharset)
encodedSignatureVale = encodedSignatureVale.replaceAll("\n", "")
println(encodedSignatureVale)
var actualValue = new String(Files.readAllBytes(Paths.get("original data")), Charset.defaultCharset)
//actualValue = actualValue.replaceAll("\n", "")
println(actualValue)
val signature = Signature.getInstance("SHA256withRSA")
//signature.initSign(privateKey)
//signature.update("Hello, Worldn".getBytes("UTF-8"))
//val signatureValue = signature.sign
//val encodedSignatureVale = Base64.encodeBase64String(signatureValue)
//println(Base64.encodeBase64String(signatureValue))

signature.initVerify(publicKey)
// signature.update("Hello, Worldn".getBytes("UTF-8"))
signature.update(actualValue.getBytes("UTF-8"))
val bool = signature.verify(Base64.decodeBase64(encodedSignatureVale))
println(bool)
if (bool) println("Signature verified")
else println("Signature failed")}

请记住,这里我同时使用了私钥和公钥。但是我们只能使用public进行验证。

签名的Perl代码将是-

use File::Slurp   qw(read_file);
use File::Slurp   qw(write_file);
use MIME::Base64  qw(encode_base64);
require Crypt::PK::RSA;
my $datatosign = read_file( 'payload.txt');
my $privatekey = Crypt::PK::RSA->new('private_key.pem');
my $signature = $privatekey->rsa_sign_message($datatosign, 'SHA256', 'v1.5');
my $hash = encode_base64($signature, '');
write_file('payload.hash', $hash);