jjzjj

ios - Obj-C 和 VB.Net 之间的加密兼容性

coder 2024-01-21 原文

加密字符串的方法大约有 100,000 种。使用 AES、CBC 和 PKCS7 等标准可以使事情变得更容易——但 IV 仍然存在问题。盐、编码等(如 www.Crypto.Stackexchange.com 所述)

对于我的 iOS 项目 (Obj-C),我正在使用 FBEncryptor project这是一种加密字符串的简单且有据可查的方法。但是,我需要能够解密 FBEncryptor 在 Windows 平台上生成的 iOS AES 字符串的代码 - 最好是 VB.NET。

我还没有找到另一个与 FBEncryptor 兼容的 VB.NET 项目。

有人知道任何与 FBEncryptor 一起工作的 VB.NET 加密项目吗?如果不是,那么我需要做什么才能使 Rijndael 托管库(由 Microsoft 提供)与 FBEncryptor 一起使用?

我的 VB.NET 代码使用 Rijndael Managed :

Imports System.Security
Imports System.Security.Cryptography
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
Imports System.Text


Module Encrypt2
Public saltBytes As Byte()
Dim hashAlgorithm As String = "SHA1"

Public Sub GenerateSalt()
    ' Define min and max salt sizes.
    Dim minSaltSize As Integer
    Dim maxSaltSize As Integer

    minSaltSize = 8
    maxSaltSize = 8

    ' Generate a random number for the size of the salt.
    Dim random As Random
    random = New Random()

    Dim saltSize As Integer
    saltSize = random.Next(minSaltSize, maxSaltSize)

    ' Allocate a byte array, which will hold the salt.
    saltBytes = New Byte(saltSize - 1) {}

    ' Initialize a random number generator.
    Dim rng As RNGCryptoServiceProvider
    rng = New RNGCryptoServiceProvider()

    ' Fill the salt with cryptographically strong byte values.
    rng.GetNonZeroBytes(saltBytes)
End Sub

Public Function Encrypt(ByVal plainText As String, ByVal keyword As String) As String
    Dim hashAlgorithm As String = "SHA1"
    Dim passwordIterations As Integer = 128
    Dim initVector As String = "@7781157e2629b09"
    Dim keySize As Integer = 256

    Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)

    Dim plainTextBytes As Byte() = Encoding.ASCII.GetBytes(plainText)

    GenerateSalt()

    Dim password As New Rfc2898DeriveBytes(keyword, saltBytes, passwordIterations)

    Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
    Dim symmetricKey As New RijndaelManaged()

    symmetricKey.Mode = CipherMode.CBC

    Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)

    Dim memoryStream As New MemoryStream()
    Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)

    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
    cryptoStream.FlushFinalBlock()
    Dim cipherTextBytes As Byte() = memoryStream.ToArray()
    memoryStream.Close()
    cryptoStream.Clear()

    Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)

    Return (cipherText)

End Function

Public Function Decrypt(ByVal cipherText As String, ByVal keyword As String) As String

    Dim hashAlgorithm As String = "SHA1"

    Dim passwordIterations As Integer = 128
    Dim initVector As String = "@7781157e2629b09"
    Dim keySize As Integer = 256

    ' Convert strings defining encryption key characteristics into Byte
    ' arrays. Let us assume that strings only contain ASCII codes.
    ' If strings include Unicode characters, use Unicode, UTF7, or UTF8
    ' encoding

    Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)

    ' Convert the Ciphertext into a Byte array
    Dim cipherTextBytes As Byte() = Encoding.ASCII.GetBytes(cipherText)

    ' First we must create a password, from which the key will be 
    ' derived. This password will be generated from the specified
    ' passphrase and salt value. The password will be created using 
    ' the specified hash algorithm. Password creation can be done in 
    ' several iterations
    GenerateSalt()
    Dim password As New Rfc2898DeriveBytes(keyword, saltBytes, passwordIterations)

    ' Use the password to generate pseudo-random bytes for the encryption
    ' key. Specify the size of the key in bytes (instead of bits)

    Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)

    ' Create uninitialized Rijndael encryption object

    Dim symmetricKey As New RijndaelManaged()

    ' It is reasonable to set encryption mode to Cipher Block Chaining
    ' (CBC). Use default options for other symmetric key parameters.
    symmetricKey.Mode = CipherMode.CBC

    ' Generate decryptor from the existing key bytes and initialization
    ' vector. Key size will be defined based on the number of the key
    'bytes

    Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)

    ' Define memory stream which will be used to hold encrypted data.

    Dim memoryStream As New MemoryStream(cipherTextBytes)

    ' Define cryptographic stream (always user Read mode for encryption).
    Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)


    ' Since at this point we don't know what the size of decrypted data
    ' will be, allocate the buffer long enough to hold ciphertext;
    ' plaintext is never longer than ciphertext
    Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}

    ' Start decrypting.
    Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)

    ' Close both streams
    memoryStream.Close()
    cryptoStream.Close()

    ' Convert decrypted data into a string
    ' Let us assume that the original plaintext string was UTF8-Encoded.
    Dim plainText As String = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)

    ' Return the decrypted string
    Return (plainText)


End Function

End Module

您会注意到 IV 是静态的并且密码迭代次数很少。这是因为我不确定如何使用与 FBEncryptor 相同的方法生成 IV。您可能还会注意到,在尝试解密时,字节长度存在问题。

任何帮助将不胜感激!谢谢!

最佳答案

一张纸条。我查看了 FBEncryptor。它使用了一些不好的做法。因此,如果安全性对您很重要,我建议您阅读更多相关内容并选择另一个进行加密的代码(或自行编写)。

FBEncryptor 做以下加密 a) 字符串转字节数组(基于UTF8编码) b) 将 key 转换为字节数组(基于 UTF 编码)。 c) 仅复制 key 的前 16 个字节 d) 创建 IV,它是 0x00 的 16 个字节 e) 使用 AES/CBC/PKCS7Padding 和在 d) 中创建的 IV 加密项目 a) 中的字节数组 f) 将得到的加密数据转为Base64

它会进行以下解密 a) 将加密字符串从 Base64 转换为字节数组 b) 将 key 转换为字节数组(基于 UTF 编码)。 c) 仅复制 key 的前 16 个字节 d) 创建 IV,它是 0x00 的 16 个字节 e) 使用 AES/CBC/PKCS7Padding 和在 d) 中创建的 IV 解密项目 a) 中的字节数组 f) 使用 UTF8 编码将 e) 中的加密数据转换为字符串

您应该在 VB.NET 中做完全相同的事情。我想你几乎所有的部分 - 您将需要删除所有 SHA1 和盐相关的东西并使用步骤 b) 的等价物。 你需要研究 PKCS7Padding for VB.NET

关于ios - Obj-C 和 VB.Net 之间的加密兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12030874/

有关ios - Obj-C 和 VB.Net 之间的加密兼容性的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  3. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  4. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  5. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  6. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  7. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  8. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  9. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  10. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

随机推荐