Sie sind auf Seite 1von 9

Antonio,

Tu código es muy bueno, pero tienes pequeños errores, el primero es que la comparación
del salt debe ser contra la secuencia de bytes que llamas OIDpkcs5PBKDF2 y lo e
stás haciendo contra OIDpkcs5PBES2.
El segundo es que los dos bytes que van después de OIDdesEDE3CBC deben ser 2 y 2,
tú estás validando 2 y 1, hay que cambiarlo.
Otro error que tienes, seguramente de concentración fue que en la función que usas p
ara comparar bytes, el incremento de i lo pones adentro del IF, debe ir después de
l END IF, si no, cada vez comparas contra el primer byte.
Por último debes revisar en la función DecodePrivateKeyInfo, donde lees el 2 y 1 del
pkcs8, asignas bt al 2 y twobytes al 1, y luego haces dos veces la comparación co
ntra bt, cuando la segunda comparación debería ir contra el 1, o sea contra twobytes
.
Haciendo estas pequeñas modificaciones, probé tu código y desencripta perfectamente cu
alquier key en PKCS8
Saludos,
Kad
..........
Imports System
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Diagnostics
Imports System.ComponentModel

Public Class clsSeguridad_2


Shared verbose As Boolean = False
Private Sub SAT()
Dim aa As String = ""
End Sub
Public Shared Function CodificarMD5(ByVal input As String) As String
Dim CadenaUTF8 As Byte()
Dim tmpHash As Byte()
'convierte en UTF8
CadenaUTF8 = Encoding.UTF8.GetBytes(input)
'crea el hash
tmpHash = New MD5CryptoServiceProvider().ComputeHash(CadenaUTF8)
Dim i As Integer
Dim sOutput As StringBuilder = New StringBuilder(tmpHash.Length)
For i = 0 To tmpHash.Length - 1 Step 1
sOutput.Append(tmpHash(i).ToString("x2"))
Next
Return sOutput.ToString()
End Function
Public Shared Function DecodeEncryptedPrivateKeyInfo(ByVal encpkcs8 As Byte(), B
yVal lSecStr As SecureString) As RSACryptoServiceProvider
Dim OIDpkcs5PBES2 As Byte() = {&H6, &H9, &H2A, &H86, &H48, &H86, &HF7, &HD, &H1,
&H5, &HD}
Dim OIDpkcs5PBKDF2 As Byte() = {&H6, &H9, &H2A, &H86, &H48, &H86, &HF7, &HD, &H1
, &H5, &HC}
Dim OIDdesEDE3CBC As Byte() = {&H6, &H8, &H2A, &H86, &H48, &H86, &HF7, &HD, &H3,
&H7}
Dim seqdes As Byte() = New Byte(10) {}
Dim seq As Byte() = New Byte(10) {}
Dim salt As Byte()
Dim IV As Byte()
Dim encryptedpkcs8 As Byte()
Dim pkcs8 As Byte()
Dim saltsize, ivsize, encblobsize As Integer
Dim iterations As Integer
' '' --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob
------
Dim mem As MemoryStream = New MemoryStream(encpkcs8)
Dim lenstream As Integer = Int(mem.Length)
Dim binr As BinaryReader = New BinaryReader(mem) 'wrap Memory Stream with Binary
Reader for easy reading
Dim bt As Byte = 0
Dim twobytes As UShort = 0
Try
twobytes = binr.ReadUInt16()
If (twobytes = &H8130) Then 'data read as little endian order (actual data order
for Sequence is 30 81)
binr.ReadByte() 'advance 1 byte
ElseIf (twobytes = &H8230) Then
binr.ReadInt16() 'advance 2 bytes
Else
Return Nothing
End If
twobytes = binr.ReadUInt16() 'inner sequence
If (twobytes = &H8130) Then
binr.ReadByte()
ElseIf (twobytes = &H8230) Then
binr.ReadInt16()
End If
seq = binr.ReadBytes(11) 'read the Sequence OID
If (Not CompareBytearrays(seq, OIDpkcs5PBES2)) Then 'is it a OIDpkcs5PBES2 ?
Return Nothing
End If

twobytes = binr.ReadUInt16() 'inner sequence for pswd salt


If (twobytes = &H8130) Then
binr.ReadByte()
ElseIf (twobytes = &H8230) Then
binr.ReadInt16()
End If
twobytes = binr.ReadUInt16() 'inner sequence for pswd salt
If (twobytes = &H8130) Then
binr.ReadByte()
ElseIf (twobytes = &H8230) Then
binr.ReadInt16()
End If
seq = binr.ReadBytes(11) 'read the Sequence OID
If (Not CompareBytearrays(seq, OIDpkcs5PBES2)) Then 'is it a OIDpkcs5PBES2 ?
Return Nothing
End If
twobytes = binr.ReadUInt16() 'inner sequence for pswd salt
If (twobytes = &H8130) Then
binr.ReadByte()
ElseIf (twobytes = &H8230) Then
binr.ReadInt16()
End If
bt = binr.ReadByte()
If (bt <> &H4) Then
Return Nothing
End If
saltsize = binr.ReadByte()
salt = binr.ReadBytes(saltsize)
If (verbose) Then
'showBytes("Salt for pbkd", salt)
End If
bt = binr.ReadByte()
If (bt <> &H2) Then 'expect an integer for PBKF2 interation count
Return Nothing
End If
Dim itbytes As Integer = binr.ReadByte() 'PBKD2 iterations should fit in 2 bytes
.
If (itbytes = 1) Then
iterations = 256 * binr.ReadByte() + binr.ReadByte()
Else
Return Nothing
End If
If (verbose) Then
Console.WriteLine("PBKD2 iterations {0}", iterations)
End If
twobytes = binr.ReadUInt16()
If (twobytes = &H8130) Then
binr.ReadByte()
ElseIf (twobytes = &H8230) Then
binr.ReadInt16()
End If
seqdes = binr.ReadBytes(10) 'read the Sequence OID
If (Not CompareBytearrays(seqdes, OIDdesEDE3CBC)) Then 'is it a OIDdes-EDE3-CBC
?
Return Nothing
End If
bt = binr.ReadByte()
If (bt <> &H4) Then 'expect octet string for IV
Return Nothing
End If
ivsize = binr.ReadByte() 'IV byte size should fit in one byte (24 expected for 3
DES)
IV = binr.ReadBytes(ivsize)
If (verbose) Then
'showBytes("IV for des-EDE3-CBC", IV)
End If
bt = binr.ReadByte()
If (bt <> &H4) Then 'expect octet string for encrypted PKCS8 data
Return Nothing
End If
bt = binr.ReadByte()
'bt = binr.ReadByte();

If (bt = &H81) Then


encblobsize = binr.ReadByte() ' data size in next byte
ElseIf (bt = &H82) Then
encblobsize = 256 * binr.ReadByte() + binr.ReadByte()
Else
encblobsize = bt ' we already have the data size
End If
encryptedpkcs8 = binr.ReadBytes(encblobsize)
Dim secpswd As SecureString = lSecStr 'GetSecPswd(lSecStr.ToString());
pkcs8 = DecryptPBDK2(encryptedpkcs8, salt, IV, secpswd, iterations)
If (pkcs8 Is Nothing) Then ' probably a bad pswd entered.
Return Nothing
End If
' ----- With a decrypted pkcs #8 PrivateKeyInfo blob, decode it to an RSA ---
Dim rsa As RSACryptoServiceProvider = DecodePrivateKeyInfo(pkcs8)
Return rsa
Catch ex As Exception
Return Nothing
Finally
binr.Close()
End Try
End Function
Private Shared Function CompareBytearrays(ByVal a As Byte(), ByVal b As Byte())
As Boolean
If (a.Length <> b.Length) Then
Return False
End If
Dim i As Integer = 0
For Each c As Byte In a
If (c <> b(i)) Then
Return False
i += 1
End If
Next
Return True
End Function
Public Shared Function DecryptPBDK2(ByVal edata As Byte(), ByVal salt As Byte(),
ByVal IV As Byte(), ByVal secpswd As SecureString, ByVal iterations As Integer)
As Byte()
Dim decrypt As CryptoStream = Nothing
'CryptoStream decrypt = null;
Dim unmanagedPswd As IntPtr = IntPtr.Zero
Dim psbytes As Byte() = New Byte(secpswd.Length) {}
unmanagedPswd = Marshal.SecureStringToGlobalAllocAnsi(secpswd)
Marshal.Copy(unmanagedPswd, psbytes, 0, psbytes.Length)
Marshal.ZeroFreeGlobalAllocAnsi(unmanagedPswd)
Try
Dim kd As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(psbytes, salt, iterations)
Dim decAlg As TripleDES = TripleDES.Create()
decAlg.Key = kd.GetBytes(24)
decAlg.IV = IV
Dim memstr As MemoryStream = New MemoryStream()
decrypt = New CryptoStream(memstr, decAlg.CreateDecryptor(), CryptoStreamMode.Wr
ite)
decrypt.Write(edata, 0, edata.Length)
decrypt.Flush()
decrypt.Close() ' this is REQUIRED.
Dim cleartext As Byte() = memstr.ToArray()
Return cleartext
Catch ex As Exception
Console.WriteLine("Problem decrypting: {0}", ex.Message)
Return Nothing
End Try
End Function
Public Shared Function DecodePrivateKeyInfo(ByVal pkcs8 As Byte()) As RSACryptoS
erviceProvider
'encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.
1.1.1"
'this byte[] includes the sequence byte and terminal encoded null
Dim SeqOID As Byte() = {&H30, &HD, &H6, &H9, &H2A, &H86, &H48, &H86, &HF7, &HD,
&H1, &H1, &H1, &H5, &H0}
Dim seq As Byte() = New Byte(15) {}
'--------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ---
---
Dim mem As MemoryStream = New MemoryStream(pkcs8)
Dim lenstream As Integer = CInt(mem.Length)
Dim binr As BinaryReader = New BinaryReader(mem) 'wrap Memory Stream with Binary
Reader for easy reading
Dim bt As Byte = 0
Dim twobytes As UShort = 0
Try
twobytes = binr.ReadUInt16()
If (twobytes = &H8130) Then 'data read as little endian order (actual data order
for Sequence is 30 81)
binr.ReadByte() 'advance 1 byte
ElseIf (twobytes = &H8230) Then
binr.ReadInt16() 'advance 2 bytes
Else
Return Nothing
End If
bt = binr.ReadByte()
If (bt <> &H2) Then
Return Nothing
End If
twobytes = binr.ReadUInt16()
If (bt <> &H1) Then
Return Nothing
End If
seq = binr.ReadBytes(15) 'read the Sequence OID
If (Not CompareBytearrays(seq, SeqOID)) Then 'make sure Sequence for OID is corr
ect
Return Nothing
End If
bt = binr.ReadByte()
If (bt <> &H4) Then
Return Nothing
End If
bt = binr.ReadByte() 'read next byte, or next 2 bytes is 0x81 or 0x82; otherwise
bt is the byte count
If (bt = &H81) Then
binr.ReadByte()
ElseIf (bt = &H82) Then
binr.ReadUInt16()
End If
'------ at this stage, the remaining sequence should be the RSA private key
Dim rsaprivkey As Byte() = binr.ReadBytes(CInt(lenstream - mem.Position))
Dim rsacsp As RSACryptoServiceProvider = DecodeRSAPrivateKey(rsaprivkey)
Return rsacsp
Catch ex As Exception
Return Nothing
' ''return null;
Finally
binr.Close()
End Try
End Function
Public Shared Function DecodeRSAPrivateKey(ByVal privkey As Byte()) As RSACrypto
ServiceProvider
Dim MODULUS, E, D, P, Q, DP, DQ, IQ As Byte()
'--------- Set up stream to decode the asn.1 encoded RSA private key ------
Dim mem As MemoryStream = New MemoryStream(privkey)
Dim binr As BinaryReader = New BinaryReader(mem) 'wrap Memory Stream with Binary
Reader for easy reading
Dim bt As Byte = 0
Dim twobytes As UShort = 0
Dim elems As Integer = 0
Try
twobytes = binr.ReadUInt16()
If (twobytes = &H8130) Then 'data read as little endian order (actual data order
for Sequence is 30 81)
binr.ReadByte() 'advance 1 byte
ElseIf (twobytes = &H8230) Then
binr.ReadInt16() 'advance 2 bytes
Else
Return Nothing
End If
twobytes = binr.ReadUInt16()
If (twobytes <> &H102) Then 'version number
Return Nothing
End If
bt = binr.ReadByte()
If (bt <> &H0) Then
Return Nothing
End If
'------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr)
MODULUS = binr.ReadBytes(elems)
elems = GetIntegerSize(binr)
E = binr.ReadBytes(elems)
elems = GetIntegerSize(binr)
D = binr.ReadBytes(elems)
elems = GetIntegerSize(binr)
P = binr.ReadBytes(elems)
elems = GetIntegerSize(binr)
Q = binr.ReadBytes(elems)
elems = GetIntegerSize(binr)
DP = binr.ReadBytes(elems)
elems = GetIntegerSize(binr)
DQ = binr.ReadBytes(elems)
elems = GetIntegerSize(binr)
IQ = binr.ReadBytes(elems)
Console.WriteLine("showing components ..")
If (verbose) Then
showBytes("\nModulus", MODULUS)
showBytes("\nExponent", E)
showBytes("\nD", D)
showBytes("\nP", P)
showBytes("\nQ", Q)
showBytes("\nDP", DP)
showBytes("\nDQ", DQ)
showBytes("\nIQ", IQ)
End If
'------- create RSACryptoServiceProvider instance and initialize with public key
-----
Dim RSA As RSACryptoServiceProvider = New RSACryptoServiceProvider()
Dim RSAparams As RSAParameters = New RSAParameters()
RSAparams.Modulus = MODULUS
RSAparams.Exponent = E
RSAparams.D = D
RSAparams.P = P
RSAparams.Q = Q
RSAparams.DP = DP
RSAparams.DQ = DQ
RSAparams.InverseQ = IQ
RSA.ImportParameters(RSAparams)
Return RSA
Catch ex As Exception
Return Nothing
End Try
binr.Close()
End Function
Public Shared Function GetIntegerSize(ByVal binr As BinaryReader) As Integer
Dim bt As Byte = 0
Dim lowbyte As Byte = &H0
Dim highbyte As Byte = &H0
Dim count As Integer = 0
bt = binr.ReadByte()
If (bt <> &H2) Then 'expect integer
Return 0
End If
bt = binr.ReadByte()
If (bt = &H81) Then
count = binr.ReadByte() 'data size in next byte
ElseIf (bt = &H82) Then
highbyte = binr.ReadByte() 'data size in next 2 bytes
lowbyte = binr.ReadByte()
Dim modint As Byte() = {lowbyte, highbyte, &H0, &H0}
count = BitConverter.ToInt32(modint, 0)
Else
count = bt 'we already have the data size
End If
While (binr.ReadByte() = &H0) 'remove high order zeros in data
count -= 1
End While
binr.BaseStream.Seek(-1, SeekOrigin.Current) 'last ReadByte wasn't a removed zer
o, so back up a byte
Return count
End Function
Private Shared Sub showBytes(ByVal info As String, ByVal data As Byte())
Console.WriteLine("{0} [{1} bytes]", info, data.Length)
For i As Integer = 1 To data.Length Step 1
Console.Write("{0:X2} ", data(i - 1))
If (i Mod 16 = 0) Then
Console.WriteLine()
End If
Next
Console.WriteLine("\n\n")
End Sub
Private Shared Function GetSecPswd(ByVal prompt As String) As SecureString
Dim password As SecureString = New SecureString
Console.ForegroundColor = ConsoleColor.Gray
Console.Write(prompt)
Console.ForegroundColor = ConsoleColor.Magenta
While (True)
Dim cki As ConsoleKeyInfo = Console.ReadKey(True)
If (cki.Key = ConsoleKey.Enter) Then
Console.ForegroundColor = ConsoleColor.Gray
Console.WriteLine()
Return password
ElseIf (cki.Key = ConsoleKey.Backspace) Then
'remove the last asterisk from the screen...
If (password.Length > 0) Then
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop)
Console.Write(" ")
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop)
password.RemoveAt(password.Length - 1)
End If
ElseIf (cki.Key = ConsoleKey.Escape) Then
Console.ForegroundColor = ConsoleColor.Gray
Console.WriteLine()
Return password
ElseIf (Char.IsLetterOrDigit(cki.KeyChar) Or Char.IsSymbol(cki.KeyChar)) Then
If (password.Length < 20) Then
password.AppendChar(cki.KeyChar)
Console.Write("*")
Else
Console.Beep()
End If
Else
Console.Beep()
End If
End While
Return password
End Function

End Class

Das könnte Ihnen auch gefallen