Android:使用存储在文件中的公钥解密RSA文本

我已经好几天试图没有成功。

在这里有很多类似的问题在StackOverflow中,甚至其中两个是完全一样的我的,但没有回答和尚未解决:1) 转换PHP RSA公钥为Android公钥 2) Android:如何解密一个opensslencryption文件与RSA密钥?

我的场景:我有一些使用RSAencryption的文本(不是由我encryption)。 我在我的res / raw文件夹中有一个“public.key”文件,其中需要解密公钥(与用于encryption邮件的私钥相关的公钥),格式如下例所示: 在这里输入图像说明

我看到很多关于如何解密RSA文本的例子,如下所示:

public static byte[] decryptRSA( PublicKey key, byte[] text) throws Exception { byte[] dectyptedText = null; Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, key); dectyptedText = cipher.doFinal(text); return dectyptedText; } 

但我的问题是,如何从文件中获得正确的PublicKey实例? 没有这个例子。

如果我只是尝试:

  InputStream is = getResources().openRawResource(R.raw.public); DataInputStream dis = new DataInputStream(is); byte [] keyBytes = new byte [(int) is.available()]; dis.readFully(keyBytes); dis.close(); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(spec); 

我在返回句子中得到一个InvalidKeyException。 我需要解码hex或Base64? 公钥文件的第一行和最后一行不是问题(“—- BEGIN PUBLIC KEY —-”等等)?

也许我们可以在StackOverflow中第一次正确地得到这个答案:-)

Solutions Collecting From Web of "Android:使用存储在文件中的公钥解密RSA文本"

终于解决了! 鼓,喇叭和一个迷人的声音交响乐!

 public static byte[] decryptRSA(Context mContext, byte[] message) throws Exception { // reads the public key stored in a file InputStream is = mContext.getResources().openRawResource(R.raw.sm_public); BufferedReader br = new BufferedReader(new InputStreamReader(is)); List<String> lines = new ArrayList<String>(); String line = null; while ((line = br.readLine()) != null) lines.add(line); // removes the first and last lines of the file (comments) if (lines.size() > 1 && lines.get(0).startsWith("-----") && lines.get(lines.size()-1).startsWith("-----")) { lines.remove(0); lines.remove(lines.size()-1); } // concats the remaining lines to a single String StringBuilder sb = new StringBuilder(); for (String aLine: lines) sb.append(aLine); String keyString = sb.toString(); Log.d("log", "keyString:"+keyString); // converts the String to a PublicKey instance byte[] keyBytes = Base64.decodeBase64(keyString.getBytes("utf-8")); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey key = keyFactory.generatePublic(spec); // decrypts the message byte[] dectyptedText = null; Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, key); dectyptedText = cipher.doFinal(Base64.decodeBase64(message)); return dectyptedText; } 

解决scheme是Base64解码不仅从文件中读取公钥,而且解密消息本身!

顺便说一下,我从文件中读取了@Nikolaybuild议的公钥(又是男人)。

非常感谢你的帮助。 StackOverflow岩石!

你错过了一个关键点 – 公钥和私钥是分开的,你不能计算一个基于另一个。 这是公共密钥encryption的一种。 抛开使用原始RSA的问题,如果你有用公钥encryption的东西,你需要有相应的私钥来解密它。 反之亦然。 所以如果你有公钥文件,你只能从中获得一个公钥。 如果你的数据是用相应的私钥encryption的,那将是有用的。

至于实际的exception:在开始和结束时删除“—”行,使用Base64.decode()来获取一个字节数组,并用它来创build你的X509EncodedKeySpec 。 一种方法 – 使用像BufferedReader一样逐行阅读,忽略“—”行,并将其余的连接成一个大的String

公钥只能encryption数据。 公钥不能解密数据。 您只能使用私钥解密数据。 关键在于你可以把公钥交给任何人和每个人,他们可以给你发送encryption的消息,只有私钥的持有者才能看到。

你真的需要非常小心使用encryption技术。 我担心你只是简单地将私钥分发给所有的设备,这将削弱你的安全性,因为每个人都有相同的私钥。 所以,如果我想破解你的安全,我只要去谷歌播放和下载你的应用程序,并将私钥从你的应用程序。 中提琴我可以看到一切。

所以你有你的答案为什么它不起作用,但你现在需要关于devise的build议,我不能告诉你为什么你使用encryption。 你在隐藏什么?

更新:

听起来就像你正在尝试像RSA如何工作一样进行encryption和签名validation,但是你却感到困惑。 为此你需要两组私钥/公钥。 一套客户端密钥和一套服务器密钥。

Web服务器将其公钥发送给客户端。 客户端可以使用服务器的公钥将经过身份validation和encryption的消息发送到服务器,然后使用客户端的私钥对该消息进行签名。 反之亦然。 服务器将使用客户端的公钥对消息进行encryption,并用私钥对其进行签名,以便向客户端发送消息。 然后,客户端可以使用客户端的私钥解密消息,并使用服务器的公钥validation签名。

现在你是否重新实施SSL? 停下来。 使用SSL。

SSL是如何实现安全通道的。 客户端接收来自Web服务器的PUBLIC密钥,以及对称encryptionalgorithm的一个或多个名称。 它select一个共同的algorithm,然后生成一个秘密密钥用于所有消息前进。 它使用Web服务器的公共密钥encryption该密钥,并将其与所选的algorithm一起发送。 Web服务器DECRYPTS使用PRIVATE键获取共享密钥。 之后,所有encryption都是使用比非对称encryption快得多的共享秘密的对称encryption。

要从您提供的PEM格式(openssl gen。rsa key)生成RSA公钥,

 -----BEGIN PUBLIC KEY----- SOMEDES3UNREADABLETEXT+PADDING== -----END PUBLIC KEY 

并用它来阅读一些与它签署的内容?

看看我的答案在这里类似的问题: https : //stackoverflow.com/a/12101100/546054