【问题标题】:Converting Coldfusion encryption code to C# (again)将 Coldfusion 加密代码转换为 C#(再次)
【发布时间】:2015-04-03 08:27:06
【问题描述】:

再一次,我的任务是将用于单点登录的 ColdFusion 代码转换为 C#,并且时间紧迫。这个问题与here 回答的问题完全不同,所以我又回到了我的脑海中。

原来的 ColdFusion 代码是在 标签中执行的。我已经用缩写占位符替换了 src 和 pwd 变量,只是为了掩盖它们的实际值:

//create a key to be used
src="xxx";
pwd="abc";

// Base64 Decoding the key
base64Decoder = createObject("java", "sun.misc.BASE64Decoder");
desKeyData = base64Decoder.decodeBuffer(pwd);


// Initialize the constructor of DESedeKeySpec with private key
KeySpec=createObject("java", "javax.crypto.spec.DESedeKeySpec");
KeySpec=KeySpec.init(desKeyData);

// Generate the secret key using SecretKeyFactory
keyFac=createObject("java", "javax.crypto.SecretKeyFactory").getInstance("DESede");
secretKey =keyFac.generateSecret(KeySpec);


// Get CIPHER OBJ ready to use
decodecipher = createObject("java", "javax.crypto.Cipher").getInstance("DESede/ECB/PKCS5Padding");
decodecipher.init(2, secretKey);

encodecipher = createObject("java", "javax.crypto.Cipher").getInstance("DESede/ECB/PKCS5Padding");

encodecipher.init(1, secretKey);

stringBytes = toString(src).getBytes("UTF8");
raw = encodecipher.doFinal(stringBytes);

// Base64Encoding of generated cipher
cipherText=ToBase64(raw);

我还有一份来自另一方的文档,其中概述了创建单点登录的步骤,如下所示:

创建加密令牌

  • 创建纯文本(这对应于上面的变量src,那部分我已经在C#中成功完成了)
  • 填充纯文本

  • 解码key(key对应上面的变量pwd,必须是base 64解码;我想我也成功了。)

  • 进行加密(使用上面得到的解码密钥和明文进行加密)

  • 对密文进行编码(url编码)

我安装了 BouncyCastle 库并尝试使用这些库,但我被困在实际的加密步骤上。到目前为止,我的 C# 转换的开始看起来是这样的(令牌和键再次缩写占位符以掩盖实际值):

//steps omitted here to create src string
string token = "xxx";
string key = "abc";
byte[] decodedKeyBytes = Convert.FromBase64String(key);

我知道这不是很多事情要做,但是我尝试了很多没有奏效的事情,以至于我迷失了方向。最终,当我到达初始化密码的部分时,我认为我需要这样的东西:

PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DesEdeEngine());

非常感谢任何建议/示例。

更新:

感谢下面非常有用的答案,我能够使用以下代码来完成这项工作:

string token = "xxx";
string key = "abc";

byte[] base64DecodedKeyBytes = Convert.FromBase64String(key);
byte[] inputBytesToken = System.Text.Encoding.UTF8.GetBytes(token);

// initialize for EBC mode and PKCS5/PKCS7 padding
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DesEdeEngine());
KeyParameter param = new KeyParameter(base64DecodedKeyBytes);
cipher.Init(true, param);

// encrypt and encode as base64
byte[] encryptedBytesToken = cipher.DoFinal(inputBytesToken);
string tokenBase64 = System.Convert.ToBase64String(encryptedBytesToken); 

【问题讨论】:

    标签: c# encryption coldfusion base64


    【解决方案1】:

    这个完全不一样

    没那么多 ;-) 你已经回答了你自己的问题。

    不要让 java 代码把你扔了。忽略一些未使用的变量,它与您的其他线程上的encrypt() 完全相同 - 除了使用“TripleDES”而不是“Blowfish”。 encrypt() 隐藏了很多复杂性,但在内部它做同样的事情 - 使用相同的 java 类 FWIW。这意味着您可以使用相同的 C# 代码。正如您已经猜到的,您只需更换加密引擎:

    ....
    // initialize for EBC mode and PKCS5/PKCS7 padding
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DesEdeEngine());
    ...
    

    更新:

    详细说明一下,当您使用encrypt( someUTF8String, base64Key, algorithm, encoding) 时,CF 在内部执行与您的 java 代码相同的步骤:

    1. 从base64解码密钥,并为给定算法创建一个KeySpec对象,即

      // Base64 Decoding the key // CF may use a different decoder, but the overall process is the same base64Decoder = createObject("java", "sun.misc.BASE64Decoder"); .... secretKey =keyFac.generateSecret(KeySpec);

    2. 接下来它会提取纯文本的 UTF-8 字节,即

      stringBytes = toString(src).getBytes("UTF8");

    3. CF 然后创建一个密码,对纯文本进行填充和加密,即:

      encodeCipher = createObject("java", "javax.crypto.Cipher").getInstance(algorithm); encodeCipher.init(1, secretKey); // 1 - ENCRYPT_MODE raw = encodeCipher.doFinal(stringBytes);

    4. 最后CF将加密后的字节编码为base64,即:

      cipherText=ToBase64(raw);

    如您所见,java 代码和encrypt 做的事情完全相同。

    【讨论】:

    • 好的,谢谢!至少我对密码初始化并不是很满意。 :) 我仍然有点不确定加密部分 - 在我的另一个问题的代码中,我只有静态密钥,但在这个我有一个密钥和一个动态生成的加密令牌,所以我'我不太确定如何在加密步骤中将两者结合起来。
    • 编辑:在加密步骤中将两者结合起来。 也许我的大脑很累,但我没有看到您发布的全部内容。原来的 CF/java 代码只是一个基本的encrypt()。使用 TripleDES 类运行 C# 代码,您将获得相同的结果。他们的意思是“使用上面的代码生成用于“Blowfish”加密的“密钥”吗?
    • 运气好吗?看起来您只是想转换 cfscript 代码。如果没有,您能否发布更多详细信息,因为听起来好像缺少一块拼图。
    • 是的,我现在终于能够完成这项工作 - 再次感谢您的帮助和非常清晰的解释,我真的很感激!正如您所指出的,我没有意识到 encrypt() 在幕后执行了许多这些步骤。 CF 代码对我来说看起来很不一样,我正忙着重新创建每一块。实际上,在没有 CF 代码供参考的情况下,尝试将指令直接翻译成 C# 可能会更好。 :) 我已经用成功的代码更新了我的帖子。
    • 是的,大部分情况下 CF 使用 java 的核心加密库。由于只有一种方法可以使用该 API,encrypt() 在内部使用与任何其他 java 应用程序相同的方法。很高兴我能帮忙:)
    猜你喜欢
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    相关资源
    最近更新 更多