一个Java类转成C#的不多,帮看下

yonglaixiazaide 2012-09-26 10:28:03
一下是JAVACode,
说明: 我改了后报错了。。汗。。不知道哪里有问题,
BigInteger 是4.0下的using System.Numerics;
new BigInteger(nStr,16); = BigInteger.Parse(nStr, System.Globalization.NumberStyles.AllowHexSpecifier);

改好后是调用方法
如果s.Length=256应该就emi问题了


BE be = new BE ();
string key = "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443";

string s = BE.Encrypt("AA", key, "10001");
int l = s.Length;


package cn.zju.topicproject.crawler;

import java.math.BigInteger;
import java.net.URLEncoder;
import java.util.Random;

import org.apache.commons.codec.binary.Base64;

public class SinaEncoder {
private static BigInteger n = null;
private static BigInteger e = null;

private static BigInteger pkcs1pad2(String s, int n){
if(n < s.length() + 11) { // TODO: fix for utf-8
System.out.println("Message too long for ");
return null;
}
byte[] ba = new byte[n];
int i = s.length()-1;
while(i >= 0 && n > 0) {
int c = s.codePointAt(i--);
if(c < 128) { // encode using utf-8
ba[--n] = new Byte(String.valueOf(c));
}
else if((c > 127) && (c < 2048)) {
ba[--n] = new Byte(String.valueOf((c & 63) | 128));
ba[--n] = new Byte(String.valueOf((c >> 6) | 192));
}
else {
ba[--n] = new Byte(String.valueOf((c & 63) | 128));
ba[--n] = new Byte(String.valueOf(((c >> 6) & 63) | 128));
ba[--n] = new Byte(String.valueOf((c >> 12) | 224));
}
}
ba[--n] = new Byte("0");

byte[] temp = new byte[1];
Random rdm = new Random(47L);

while(n > 2) { // random non-zero pad
temp[0] = new Byte("0");
while(temp[0] == 0)
rdm.nextBytes(temp);
ba[--n] = temp[0];
}
ba[--n] = 2;
ba[--n] = 0;

return new BigInteger(ba);
}

private static BigInteger DoPublic(BigInteger x){
return x.modPow(e, n);
}


public static String Encrypt(String pwd, String nStr, String eStr){
n = new BigInteger(nStr,16);
e = new BigInteger(eStr,16);

BigInteger r = DoPublic(pkcs1pad2(pwd,(n.bitLength()+7)>>3));
String sp = r.toString(16);
if((sp.length()&1) != 0 )
sp = "0" + sp;
return sp;
}
}


我改的C#代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Data;
using System.Numerics;
using System.Text;
namespace Spider.Test
{
/// <summary>
///Class1 的摘要说明
/// </summary>
public class BE
{
public ()
{

//
//TODO: 在此处添加构造函数逻辑
//

}
private static BigInteger n = new BigInteger();
private static BigInteger e = new BigInteger();
private static BigInteger pkcs1pad2(String s, int n)
{
if (n < s.Length + 11)
{ // TODO: fix for utf-8
//System.out.println("Message too long for ");
return 0;
}
byte[] ba = new byte[n];
int i = s.Length - 1;
while (i >= 0 && n > 0)
{
int c = s.IndexOf((i--).ToString());
if (c < 128)
{ // encode using utf-8
ba[--n] = byte.Parse(c.ToString());
}
else if ((c > 127) && (c < 2048))
{
ba[--n] = byte.Parse(((c & 63) | 128).ToString());
ba[--n] = byte.Parse(((c >> 6) | 192).ToString());
}
else
{
ba[--n] = byte.Parse(((c & 63) | 128).ToString());
ba[--n] = byte.Parse((((c >> 6) & 63) | 128).ToString());
ba[--n] = byte.Parse(((c >> 12) | 224).ToString());
}
} ba[--n] = byte.Parse("0");
byte[] temp = new byte[1];
Random rdm = new Random(47);
while (n > 2)
{ // random non-zero pad
temp[0] = byte.Parse("0");
while (temp[0] == 0)
rdm.NextBytes(temp);
ba[--n] = temp[0];
} ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}
private static BigInteger DoPublic(BigInteger x)
{
return BigInteger.ModPow(x, e, n);

}
/// <summary>
/// Base64加密
/// </summary>
/// <param name="codeName">加密采用的编码方式</param>
/// <param name="source">待加密的明文</param>
/// <returns></returns>
public static string EncodeBase64(Encoding encode, string source)
{
byte[] bytes = encode.GetBytes(source);
try
{
source = Convert.ToBase64String(bytes);
}
catch
{
source = source;
}
return source;
}

/// <summary>
/// Base64加密,采用utf8编码方式加密
/// </summary>
/// <param name="source">待加密的明文</param>
/// <returns>加密后的字符串</returns>
public static string EncodeBase64(string source)
{
return EncodeBase64(Encoding.UTF8, source);
}
public static String Encrypt(String pwd, String nStr, String eStr)
{
n = BigInteger.Parse(nStr, System.Globalization.NumberStyles.AllowHexSpecifier);
e = BigInteger.Parse(eStr, System.Globalization.NumberStyles.AllowHexSpecifier);
BigInteger r = DoPublic(pkcs1pad2(pwd, (n.ToByteArray().Length + 7) >> 3));
String sp = r.ToString(System.Globalization.NumberStyles.AllowHexSpecifier.ToString());

if ((sp.Length & 1) != 0)
sp = "0" + sp;
return sp;
}

}
}

...全文
217 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
嗯,嗯,,我也想整明白,那个方法 太让我纠结了。。没说明,,简直就是天书一样,
(n.bitLength()+7)>>3 后面用到的地方 就是 一个判断长度,其他的也没见地方用。。。
谢谢 真么细心~

[Quote=引用 14 楼 的回复:]
引用 12 楼 的回复:

你检查一下字符长度、位移,c#和java不一样的

请不要乱说,这些都是一样的。

我觉得楼主应该先看懂算法,然后才能改写,那个(n.bitLength()+7)>>3的作用你必须看明白,我虽然没仔细看,但多少也猜测出来了,是为了处理符号位。
关于符号位,我之前忘记说了,Java和C#除了那个高位地位哪个在前不同之外,还有一个不容易被发现的不同就是byte……
[/Quote]
qldsrx 2012-09-26
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

你检查一下字符长度、位移,c#和java不一样的
[/Quote]
请不要乱说,这些都是一样的。

我觉得楼主应该先看懂算法,然后才能改写,那个(n.bitLength()+7)>>3的作用你必须看明白,我虽然没仔细看,但多少也猜测出来了,是为了处理符号位。
关于符号位,我之前忘记说了,Java和C#除了那个高位地位哪个在前不同之外,还有一个不容易被发现的不同就是byte的含义不一样,Java中的byte等价于C#的sbyte,也就是带符号的字节,Java中不存在不带符号的字节,所以在Java中的字节处理非常麻烦,时刻要考虑符号位的处理,但这在C#里面用无符号byte就变得非常简单。
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
我测试后,加密后长度 是256位,也没报错,至于是不是正确的,现在还不好验证。。
[Quote=引用 12 楼 的回复:]
你检查一下字符长度、位移,c#和java不一样的
[/Quote]
lshfong 2012-09-26
  • 打赏
  • 举报
回复
你检查一下字符长度、位移,c#和java不一样的
lshfong 2012-09-26
  • 打赏
  • 举报
回复
你检查一下字符长度、位移,c#和java不一样的
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
我觉得这个长度 只是判断而已,貌似 在整个算法中关系不大,,我改为了右移3位。。。。
目前 都能通过了。。。。加密出来的都是256的密文了,,现在就差验证了~
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
n.ToByteArray()=128
128+7=135;
135右移3为16.。我试试左移。。
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
受教了,运算的那个 先放下,先有这个问题,如果密码长度小于5的,加密出来的结果是16进制的256位,看起来没问题,只是我还和某个平台验证,

String nStr 参数是固定的密钥256为
n = BigInteger.Parse(nStr, System.Globalization.NumberStyles.AllowHexSpecifier)
n.ToByteArray().Length + 7) >> 3(JAVA:,(n.bitLength()+7)>>3))

一个byte是8位 是否等价于java中的bit?
由于密钥是固定的,这个长度也是固定的,算出来的是16为。。
这个n=n.ToByteArray().Length + 7) >>
S是密码的长度。。
if (n < s.Length + 11)
{ // TODO: fix for utf-8
//System.out.println("Message too long for ");
return 0;
}
所以。。。

[Quote=引用 7 楼 的回复:]
建议用X2,而不是X,X2的话,不足2位前面补0,否则16进制字符串将不会对其。
[/Quote]
qldsrx 2012-09-26
  • 打赏
  • 举报
回复
建议用X2,而不是X,X2的话,不足2位前面补0,否则16进制字符串将不会对其。
qldsrx 2012-09-26
  • 打赏
  • 举报
回复
哦,你修改了一个自己范的小错误,其实s.ElementAt(i--)也可以简写成:s[i--],直接用索引访问更方便。
至于结果问题,就是我前面说的,必须字节反转。
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
最后的那个BigInteger转16进制
String sp = r.ToString(System.Globalization.NumberStyles.AllowHexSpecifier.ToString());
改为
String sp = r.ToString("X");

这样的如果要加密的内容小于5加密的是256 自己,比较靠谱,
我这里n是16 。。
if (n < s.Length + 11)
{ // TODO: fix for utf-8
//System.out.println("Message too long for ");
return 0;
}
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
JAVA中的 s.codePointAt(i--);
不是
s.IndexOf((i--).ToString());
而是这个
s.ElementAt(i--)
现在 不报错了,只是结果,有问题。。应该位运算上的问题
[Quote=引用 3 楼 的回复:]
你不是用的ToByteArray吗?那个没错。
关键是你的那个pkcs1pad2方法啊,里面先初始化一个“byte[] ba = new byte[n];”,然后对这个ba设置每个字节,最后返回“return new BigInteger(ba);”,这是Java的正常流程,但是C#里面就必须翻过来。例如,Java对ba的索引0的字节设置内容,C#就应该对索引n-1的字节设置内容,你也可以按照J……
[/Quote]
qldsrx 2012-09-26
  • 打赏
  • 举报
回复
你不是用的ToByteArray吗?那个没错。
关键是你的那个pkcs1pad2方法啊,里面先初始化一个“byte[] ba = new byte[n];”,然后对这个ba设置每个字节,最后返回“return new BigInteger(ba);”,这是Java的正常流程,但是C#里面就必须翻过来。例如,Java对ba的索引0的字节设置内容,C#就应该对索引n-1的字节设置内容,你也可以按照Java的顺序设置好了然后反转数组。
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
唉,就是啊,,郁闷,感觉应该是n.bitLength() 这个方法查了下,是不包括符号的bit数,bit=8位?
这个转换。。byte貌似不行。。BigInteger 也不知道怎么转二进制 int倒是知道。。

[Quote=引用 1 楼 的回复:]
代码我不详细看了,仅指出Java和C#转换时必须注意的问题,也是你这里报错的最主要问题(至于是否还有其它问题不清楚)。

Java中的多字节数字(例如int是4字节的)都是高字节在前,低字节在后,而C#、C++等语言是按照实际CPU的存储方式,低字节在前,高字节在后。所以这里的BigInteger在处理的时候就有很大的区别,必须内部字节反转才能正确。(你这里的算法用的为位运算,不反转的话,位运……
[/Quote]
qldsrx 2012-09-26
  • 打赏
  • 举报
回复
代码我不详细看了,仅指出Java和C#转换时必须注意的问题,也是你这里报错的最主要问题(至于是否还有其它问题不清楚)。

Java中的多字节数字(例如int是4字节的)都是高字节在前,低字节在后,而C#、C++等语言是按照实际CPU的存储方式,低字节在前,高字节在后。所以这里的BigInteger在处理的时候就有很大的区别,必须内部字节反转才能正确。(你这里的算法用的为位运算,不反转的话,位运算就肯定出错)
yonglaixiazaide 2012-09-26
  • 打赏
  • 举报
回复
真是 谢谢这么细心的解答,还这么详细,拜膜下。。,你说的很对,
只要n.ToByteArray().Length即可,不要什么+7啊,移位啊,那个就是画蛇添足了。
>>3是除以8 如果不除8 我对位运算 也研究过一阵子,只是有的算法为什么要这么写 还不是很懂。。 肯定可以通过了。嘿嘿,结贴了,分都给你,貌似。我只能发100分的贴,也加不了分,就都给你了
[Quote=引用 16 楼 的回复:]
建议你查询下Java的API手册:http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigInteger.html
这里写着那个bitLength用法,给你翻译下:
返回带符号的二进制补码的最小位数。(注意,不是十六进制的字节个数)

这样你就应该明白为啥是(n.bitLength()+7)>>3了吧。首先把>>3理解为除以8,因……
[/Quote]
qldsrx 2012-09-26
  • 打赏
  • 举报
回复
建议你查询下Java的API手册:http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigInteger.html
这里写着那个bitLength用法,给你翻译下:
返回带符号的二进制补码的最小位数。(注意,不是十六进制的字节个数)

这样你就应该明白为啥是(n.bitLength()+7)>>3了吧。首先把>>3理解为除以8,因为一个数右移3位等价于除以8,而+7则是为了补足符号位,那个bitLength返回的二进制补码位数有可能不足一个字节的长度,例如数字1,它得到的二进制补码最小位数是1,但是一个字节是8位的,如果用1除以8,则一个字节都没有满,因此+7后正好补足8位,这样对于不满一个字节长度的二进制数,也算上一个字节了。整个计算的结果就是得到n中间的16进制字节个数,因此你用C#写,只要n.ToByteArray().Length即可,不要什么+7啊,移位啊,那个就是画蛇添足了。

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧