简体   繁体   English

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

[英]Migrate Public/Private Keys from one programming language to other for Signing Payload and verifying them

I have one Perl Script that sign the payload with private key(id_rsa), generated in linux machine with SSH-Keygen or OpenSSL. After that I am taking the hash or the signed value, decoding it in base 64 and sending to my scala code.我有一个 Perl 脚本,它使用私钥 (id_rsa) 对有效载荷进行签名,在带有 SSH-Keygen 或 OpenSSL 的机器中生成。之后我将使用 hash 或签名值,在 base 64 中对其进行解码并发送到我的 scala 代码. Here I send two things, the public key(id_rsa.pub) and the encoded signature.在这里我发送了两件事,公钥(id_rsa.pub)和编码签名。

Now when I verify the signature it always give me false result.现在,当我验证签名时,它总是给我错误的结果。 I have tried the opposite, like singing in Scala and verifying with Perl. It returned me false.我试过相反的方法,比如在 Scala 中唱歌,然后用 Perl 验证。它返回我的错误。 I generated the keys in Scala and put them in Linux and done the signing and verifying part from Perl. It worked.我在 Scala 中生成了密钥并将它们放在 Linux 中,并从 Perl 完成了签名和验证部分。它起作用了。 It even worked when I imported both keys in scala and try to do the signing and verifying part both from scala.当我在 scala 中导入两个密钥并尝试从 scala 进行签名和验证部分时,它甚至起作用了。

But whenever I am mixing up these two like signing in Perl and verifying in Scala or signing in Scala and verifying in Perl, it is giving me a false result.但是每当我混淆这两者时,比如登录 Perl 并在 Scala 中验证,或者登录 Scala 并在 Perl 中验证,它就会给我一个错误的结果。

My question is is there any common format that I can use here.我的问题是有没有我可以在这里使用的通用格式。 The code I am using is -我使用的代码是 -

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")
}

I have found a solution.我找到了解决办法。 I achieved that by correcting the signature algorithm and its default values in Perl. Also you have to take care of the new line characters (\n).我通过更正 Perl 中的签名算法及其默认值来实现这一点。您还必须注意换行符 (\n)。 The modified code for verification should look like this in Scala -修改后的校验代码在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, World\n".getBytes("UTF-8"))
  //val signatureValue = signature.sign
  //val encodedSignatureVale = Base64.encodeBase64String(signatureValue)
  //println(Base64.encodeBase64String(signatureValue))


  signature.initVerify(publicKey)
  // signature.update("Hello, World\n".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")}

Remember I have taken both private and public key here.请记住,我在这里同时使用了私钥和公钥。 But we can use only public for verification.但是我们只能使用 public 来进行验证。

The Perl code for signing will be - 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM