Open luckyPandaBear opened 1 year ago
The problems is here in rsa.cpp
:
OID RSAFunction::GetAlgorithmID() const
{
return ASN1::rsaEncryption();
}
rsaEncryption
is OID 1.2.840.113549.1.1.1
. It causes the exception in PKCS8PrivateKey::BERDecode
when BERDecodeAndCheck
is called.
I think the quickest workaround is to add a RSA_PSS
, which uses the expected OID:
$ git diff
diff --git a/rsa.h b/rsa.h
index 3f2312ee..330fc33f 100644
--- a/rsa.h
+++ b/rsa.h
@@ -155,6 +155,26 @@ public:
Integer PreimageBound() const {return ++(m_n>>1);}
};
+/// \brief RSA trapdoor function using the public key
+/// \since Crypto++ 1.0
+class CRYPTOPP_DLL RSAFunction_PSS : public RSAFunction
+{
+public:
+ OID GetAlgorithmID() const {
+ return ASN1::rsassa_pss();
+ }
+};
+
+/// \brief RSA trapdoor function using the private key
+/// \since Crypto++ 1.0
+class CRYPTOPP_DLL InvertibleRSAFunction_PSS : public InvertibleRSAFunction
+{
+public:
+ OID GetAlgorithmID() const {
+ return ASN1::rsassa_pss();
+ }
+};
+
/// \brief RSA algorithm
/// \since Crypto++ 1.0
struct CRYPTOPP_DLL RSA
@@ -164,6 +184,15 @@ struct CRYPTOPP_DLL RSA
typedef InvertibleRSAFunction PrivateKey;
};
+/// \brief RSA algorithm
+/// \since Crypto++ 1.0
+struct CRYPTOPP_DLL RSA_PSS
+{
+ CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "RSA";}
+ typedef RSAFunction_PSS PublicKey;
+ typedef InvertibleRSAFunction_PSS PrivateKey;
+};
+
/// \brief RSA encryption algorithm
/// \tparam STANDARD signature standard
/// \sa <a href="http://www.weidai.com/scan-mirror/ca.html#RSA">RSA cryptosystem</a>
And then in your program:
RSA_PSS::PrivateKey rsa;
FileSource fs("privKey.pkcs8", true);
rsa.Load(fs);
A new RSA_PSS
class is not the only way to solve the problem. Here is another way, which is mostly a copy/paste/modify of PKCS8PrivateKey::BERDecode
.
#include "config.h"
#include "files.h"
#include "oids.h"
#include "asn.h"
#include "rsa.h"
using namespace CryptoPP;
bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
{
BERDecodeNull(bt);
return false;
}
RSA::PrivateKey LoadAndCheck(BufferedTransformation& bt, const OID& oid /*expected*/)
{
BERSequenceDecoder privateKeyInfo(bt);
word32 version;
BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
BERSequenceDecoder algorithm(privateKeyInfo);
oid.BERDecodeAndCheck(algorithm);
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
algorithm.MessageEnd();
BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
RSA::PrivateKey key;
key.BERDecodePrivateKey(octetString, parametersPresent, octetString.RemainingLength());
octetString.MessageEnd();
privateKeyInfo.MessageEnd();
return key;
}
int main(int argc, char* argv[])
{
FileSource fs("RSAPrivPSS.pkcs8", true);
RSA::PrivateKey key = LoadAndCheck(fs, ASN1::rsassa_pss());
return 0;
}
RSAPrivKeys.zip
When importing RSA private key files as attached, Crypto++ seems to support structures containing the OID for "rsaEncryption" (1 2 840 113549 1 1 1) only. Whenever a private key file is presented indicating the OID for "rsaPSS" (1 2 840 113549 1 1 10), the Load() function throws a "BERDecode error" exception.
Sample code:
The same behaviour applies to:
Why is it not possible to import key files with "rsaPSS" OID included?