So che la risposta principale che probabilmente otterrò è perché diavolo vorresti farlo ?!Utilizzo di una chiave pubblica RSA per decrittografare una stringa crittografata utilizzando la chiave privata RSA
Purtroppo nonostante le mie proteste devo farlo, anche se so che non ha molto senso.
Ho funzioni scritte in .Net per decodificare utilizzando una chiave privata, crittografare utilizzando una chiave pubblica. Ho anche firmato RSA e verificare e avere una ragionevole comprensione di come tutto questo funzioni, penso.
Attualmente mi viene inviato un valore RSA crittografato utilizzando una chiave privata che dovrei ricavare un valore utilizzabile decifrando utilizzando la chiave pubblica.
Non riesco a capire come farlo. Sono un idiota? È normale?
Mi viene detto dalla persona che mi invia il valore che questo non è un problema in PHP. Non lo so e non ho ancora usato PHP. Non riesco a trovare una libreria per farlo in una delle lingue principali che conosco, C++, Java, C#. Il server su cui sto lavorando utilizza .Net.
Spero che qualcuno possa aiutarmi.
Sarebbe bello se esistesse una soluzione ragionevole oltre a implorare loro di cambiare ciò che stavano facendo.
Questo è il mio metodo (aggiornato dal mio precedente cattivo come sottolineato da Iridium), ma quando cerco di decifrare il valore ottengo un'eccezione
"Errore durante la decodifica imbottitura OAEP."
Se uso rsa.Decrypt (byte, falso) ottengo un'eccezione chiave errata.
public static string DecryptUsingPublic(string dataEncrypted, string publicKey)
{
if (dataEncrypted == null) throw new ArgumentNullException("dataEncrypted");
if (publicKey == null) throw new ArgumentNullException("publicKey");
try
{
RSAParameters _publicKey = LoadRsaPublicKey(publicKey, false);
RSACryptoServiceProvider rsa = InitRSAProvider(_publicKey);
byte[] bytes = Convert.FromBase64String(dataEncrypted);
byte[] decryptedBytes = rsa.Decrypt(bytes, true);
ArrayList arrayList = new ArrayList();
arrayList.AddRange(decryptedBytes);
return Encoding.UTF8.GetString(decryptedBytes);
}
catch
{
return null;
}
}
private static RSAParameters LoadRsaPublicKey(String publicKeyFilePath, Boolean isFile)
{
RSAParameters RSAKeyInfo = new RSAParameters();
byte[] pubkey = ReadFileKey(publicKeyFilePath, "PUBLIC KEY", isFile);
byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
byte[] seq = new byte[15];
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
MemoryStream mem = new MemoryStream(pubkey);
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return RSAKeyInfo;
seq = binr.ReadBytes(15); //read the Sequence OID
if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct
return RSAKeyInfo;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8203)
binr.ReadInt16(); //advance 2 bytes
else
return RSAKeyInfo;
bt = binr.ReadByte();
if (bt != 0x00) //expect null byte next
return RSAKeyInfo;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return RSAKeyInfo;
twobytes = binr.ReadUInt16();
byte lowbyte = 0x00;
byte highbyte = 0x00;
if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
else if (twobytes == 0x8202)
{
highbyte = binr.ReadByte(); //advance 2 bytes
lowbyte = binr.ReadByte();
}
else
return RSAKeyInfo;
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
int modsize = BitConverter.ToInt32(modint, 0);
byte firstbyte = binr.ReadByte();
binr.BaseStream.Seek(-1, SeekOrigin.Current);
if (firstbyte == 0x00)
{ //if first byte (highest order) of modulus is zero, don't include it
binr.ReadByte(); //skip this null byte
modsize -= 1; //reduce modulus buffer size by 1
}
byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
return RSAKeyInfo;
int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
byte[] exponent = binr.ReadBytes(expbytes);
RSAKeyInfo.Modulus = modulus;
RSAKeyInfo.Exponent = exponent;
return RSAKeyInfo;
}
catch (Exception)
{
return RSAKeyInfo;
}
finally { binr.Close(); }
//return RSAparams;
}
private static RSACryptoServiceProvider InitRSAProvider(RSAParameters rsaParam)
{
//
// Initailize the CSP
// Supresses creation of a new key
//
CspParameters csp = new CspParameters();
//csp.KeyContainerName = "RSA Test (OK to Delete)";
const int PROV_RSA_FULL = 1;
csp.ProviderType = PROV_RSA_FULL;
const int AT_KEYEXCHANGE = 1;
// const int AT_SIGNATURE = 2;
csp.KeyNumber = AT_KEYEXCHANGE;
//
// Initialize the Provider
//
RSACryptoServiceProvider rsa =
new RSACryptoServiceProvider(csp);
rsa.PersistKeyInCsp = false;
//
// The moment of truth...
//
rsa.ImportParameters(rsaParam);
return rsa;
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
while (binr.ReadByte() == 0x00)
{ //remove high order zeros in data
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
return count;
}
private static bool CompareBytearrays(byte[] a, byte[] b)
{
if (a.Length != b.Length)
return false;
int i = 0;
foreach (byte c in a)
{
if (c != b[i])
return false;
i++;
}
return true;
}
I due metodi precedenti InitRSAProvider e LoadRsaPublicKey stati ottenuti su tutorial per consentire tasti PEM come stringhe da utilizzare con Net.
Say what? Questo è esattamente ciò che l'algoritmo dovrebbe fare. Decifrare usando una chiave privata ciò che è stato crittografato usando la chiave pubblica corrispondente. O sei confuso alla grande o sono io! C# supporta perfettamente RSA :) –
Siamo spiacenti. Modificato la mia domanda. L'ho scritto completamente sbagliato. Il cervello inizia a arrampicarsi un po 'il venerdì. –
Cosa non riesci a capire? Dici di avere già funzioni per decodificare usando una chiave pubblica. – James