Java和子字符串错误
我正在实现一种用密钥加密的方法,我做了如下调用:Java和子字符串错误,java,indexing,substring,Java,Indexing,Substring,我正在实现一种用密钥加密的方法,我做了如下调用: Crypto c = new Crypto("mysecretkey"); String enc = c.encrypt("mytext"); 但我有个例外 “加密错误:字符串索引超出范围:-1” 在本部分: String sKeyChar = getKey().substring((i % getKey().length()) - 1, 1); 我不知道我做错了什么,因为我用PHP做了同样的事情,效果很好。也许这很简单,但我被卡住了,这是我
Crypto c = new Crypto("mysecretkey");
String enc = c.encrypt("mytext");
但我有个例外
“加密错误:字符串索引超出范围:-1”
在本部分:
String sKeyChar = getKey().substring((i % getKey().length()) - 1, 1);
我不知道我做错了什么,因为我用PHP做了同样的事情,效果很好。也许这很简单,但我被卡住了,这是我的方法:
public String encrypt(String sData) {
String sEncrypted = null;
try {
String sResult = null;
for (int i = 0; i < sData.length(); i++) {
String sChar = sData.substring(i, 1);
String sKeyChar = getKey().substring((i % getKey().length()) - 1, 1);
char c = (char) (ord(sChar) - ord(sKeyChar));
String sPart = (new StringBuffer().append(c)).toString();
sResult += sPart;
}
byte[] sResultBuff = sResult.getBytes("UTF-8");
sEncrypted = Base64.encode(sResultBuff);
} catch (Exception e) {
System.out.println("crypto encrypt error: " + e.getMessage());
sEncrypted = null;
}
return sEncrypted;
}
PHP等效方法:
function encrypt($sData, $sKey='mysecretkey'){
$sResult = '';
for($i=0;$i<strlen($sData);$i++){
$sChar = substr($sData, $i, 1);
$sKeyChar = substr($sKey, ($i % strlen($sKey)) - 1, 1);
$sChar = chr(ord($sChar) + ord($sKeyChar));
$sResult .= $sChar;
}
return encode_base64($sResult);
}
函数加密($sData,$sKey='mysecretkey'){
$sResult='';
对于($i=0;$i您的计算是错误的:(i%getKey().length())-1
将导致i=0
的-1,即在第一次迭代中正确。因此您尝试将-1传递给子字符串(…)
方法,这是不允许的
还要注意,如果数据比键长,i%getKey().length()
将导致键长的每倍数为0
此外,子字符串(…)
的参数不是索引
和长度
,而是开始索引
(包含)和结束索引
(排除)。因此字符串sChar=sData。子字符串(i,1);
一旦i
达到2(及以上)就会抛出异常并且不会为i=1
返回任何内容
您可能希望改用charAt(i)
(以及getKey().charAt(i%getKey().length())
,请注意,这将返回单个字符,这将使ord(…)
方法过时
作为旁注:String.valueOf(sChar.charAt(0)).codePointAt(0)
相当于sChar.codePointAt(0)
另一个旁注:
char c = (char) (ord(sChar) - ord(sKeyChar));
String sPart = (new StringBuffer().append(c)).toString();
sResult += sPart;
可以简化为
char c = (char) (ord(sChar) - ord(sKeyChar));
sResult += c; //you could also merge those two lines
您可以看到PHP和Java之间的区别,因为PHP的substr
理解负数,而Java的substring
不理解负数:它抛出一个异常
在PHP中,将负1传递给substr
意味着“获取最后一个字符”,但在Java中,需要传递最后一个字符的索引(即str.length()-1
)才能达到相同的效果
如果这不是一个错误,并且这正是您想要达到的效果,您可以使用If
条件来解决此问题:
int pos = (i % getKey().length()) - 1;
if (pos == -1) {
pos = getKey().length() - 1;
}
// EDIT: Second argument needs to be pos+1, not 1. Thomas pointed out this error
String sKeyChar = getKey().substring(pos, pos+1);
EDIT正如Thomas正确指出的那样,PHP版本的substr
和Java的substring
之间的另一个区别在于它们对第二个参数的处理:PHP认为它是长度;Java认为它是最后一个字符加上一个字符的索引。如前所述,PHP中的substr具有不同的语义在Java中。
在PHP中
string substr(string$string,int$start[,int$length])
它也接受负数(这会改变它的行为)
在java中,它被定义为:
String substring(int beginIndex, int endIndex)
如果beginIndex
大于endIndex
,则对负数抛出异常。
总而言之,它们是不同的,你需要对此进行补偿。你也应该发布getKey()
方法,因为它在line中使用,但失败了。我认为这不是加密安全的想法是错误的吗?我觉得我应该能够从中猜出密钥和数据,知道该方法(假设短密钥)。这是假设减法运算的结果是一个有效的char
,不管怎样;ord()
方法并不总是返回有效的数据,并且不是国际安全的(组合字符)。此外,您正在吞咽异常,这是不好的,只需打印到系统。out
(甚至不是.err
!),而不是正确地记录。并查找StringBuilder
-您的实现不是最佳的。感谢您的推荐,但这只是一个测试方法和getKey()很好如果有人给我打分,解释一下原因会很好。谢谢你的解释,这真的很有用。如果pos
不是0或1,就会产生一个异常。@Thomas你完全正确,这是PHP和Java之间的另一个区别。在这一点上,我认为你的解决方案是正确的(使用单个字符而不是一个字符串)更干净,所以我将对其进行升级。感谢您发现此错误!感谢您提供的解决方案:)我在ord()中的“char c=(char)(ord(sChar)-ord(sKeyChar));”这一行仍然遇到错误方法,但我会继续寻找正在发生的事情。但一切都清楚,再次感谢!
String substring(int beginIndex, int endIndex)