Java throws clause – sonarqube issue

huangapple go评论58阅读模式
英文:

Java throws clause - sonarqube issue

问题

我有一些旧的代码,在其中运行了 SonarQube。我对 Java、异常继承等方面不是专家,所以希望有人能够帮助我解决这个问题,因为 SonarQube 指出这是一个 阻塞问题

这是代码:

package xxx;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class Encryptor {

    private static final String ALGORITHM = "AES";

    private static final String defaultSecretKey = "xxx";

    private Key secretKeySpec;

    public Encryptor() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
            UnsupportedEncodingException {
        this(null);
    }

    public Encryptor(String secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            UnsupportedEncodingException {
        this.secretKeySpec = generateKey(secretKey);
    }

    public String encrypt(String plainText) throws InvalidKeyException, NoSuchAlgorithmException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
        return asHexString(encrypted);
    }

    public String decrypt(String encryptedString) throws InvalidKeyException, IllegalBlockSizeException,
            BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        byte[] original = cipher.doFinal(toByteArray(encryptedString));
        return new String(original);
    }

    private Key generateKey(String secretKey) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if (secretKey == null) {
            secretKey = defaultSecretKey;
        }
        byte[] key = (secretKey).getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-256");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16);

        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(256);

        return new SecretKeySpec(key, ALGORITHM);
    }

    private final String asHexString(byte buf[]) {
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;
        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10) {
                strbuf.append("0");
            }
            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }
        return strbuf.toString();
    }

    private final byte[] toByteArray(String hexString) {
        int arrLength = hexString.length() >> 1;
        byte buf[] = new byte[arrLength];
        for (int ii = 0; ii < arrLength; ii++) {
            int index = ii << 1;
            String l_digit = hexString.substring(index, index + 2);
            buf[ii] = (byte) Integer.parseInt(l_digit, 16);
        }
        return buf;
    }

    public static void main(String[] args) throws Exception {
        if (args.length == 1) {
            String plainText = args[0];
            Encryptor aes = new Encryptor();
            String encryptedString = aes.encrypt(plainText);
            String decryptedString = aes.decrypt(encryptedString);
            System.out.println("Original Password: " + plainText + " and Encrypted Password: " + encryptedString);
        } else {
            System.out.println("USAGE: java AES string-to-encrypt");
        }
    }
}

问题出现在这一行:

public static void main(String[] args) throws Exception {

SonarQube 建议 移除此 throws 子句

有人知道如何解决这个问题或者为什么会出现这个问题吗?

非常感谢。

M.

英文:

I have kind of old code where we run sonarqube. I am not expert on Java and Exception descendants etc. so I hope someone will be able to help me to fix this issue, as Sonar says it is a blocker.

This is the code:

package xxx;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class Encryptor {
private static final String ALGORITHM = &quot;AES&quot;;
private static final String defaultSecretKey = &quot;xxx&quot;;
private Key secretKeySpec;
public Encryptor() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
UnsupportedEncodingException {
this(null);
}
public Encryptor(String secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
UnsupportedEncodingException {
this.secretKeySpec = generateKey(secretKey);
}
public String encrypt(String plainText) throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes(&quot;UTF-8&quot;));
return asHexString(encrypted);
}
public String decrypt(String encryptedString) throws InvalidKeyException, IllegalBlockSizeException,
BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] original = cipher.doFinal(toByteArray(encryptedString));
return new String(original);
}
private Key generateKey(String secretKey) throws UnsupportedEncodingException, NoSuchAlgorithmException {
if (secretKey == null) {
secretKey = defaultSecretKey;
}
byte[] key = (secretKey).getBytes(&quot;UTF-8&quot;);
MessageDigest sha = MessageDigest.getInstance(&quot;SHA-256&quot;);
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only the first 128 bit
KeyGenerator kgen = KeyGenerator.getInstance(&quot;AES&quot;);
kgen.init(256); // 192 and 256 bits may not be available
return new SecretKeySpec(key, ALGORITHM);
}
private final String asHexString(byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i &lt; buf.length; i++) {
if (((int) buf[i] &amp; 0xff) &lt; 0x10) {
strbuf.append(&quot;0&quot;);
}
strbuf.append(Long.toString((int) buf[i] &amp; 0xff, 16));
}
return strbuf.toString();
}
private final byte[] toByteArray(String hexString) {
int arrLength = hexString.length() &gt;&gt; 1;
byte buf[] = new byte[arrLength];
for (int ii = 0; ii &lt; arrLength; ii++) {
int index = ii &lt;&lt; 1;
String l_digit = hexString.substring(index, index + 2);
buf[ii] = (byte) Integer.parseInt(l_digit, 16);
}
return buf;
}
public static void main(String[] args) throws Exception {
if (args.length == 1) {
String plainText = args[0];
Encryptor aes = new Encryptor();
String encryptedString = aes.encrypt(plainText);
//this line only ensures that decryption works
String decryptedString = aes.decrypt(encryptedString);
System.out.println(&quot;Original Password: &quot; + plainText + &quot; and Encrypted Password: &quot; + encryptedString);
} else {
System.out.println(&quot;USAGE: java AES string-to-encrypt&quot;);
}
}
}

And problem is on this line:

public static void main(String[] args) throws Exception {

Sonar says Remove this throws clause

Does anybody know how to fix this or why is this happening?

Thanks a lot.

M.

答案1

得分: 0

感谢所有的评论:

这是解决方案(移除通用异常并添加明确的异常处理):

public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
英文:

Thanks to all comments:

This is solution (removal of generic exception and adding explicit exceptions):

public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {

答案2

得分: 0

这总是一个不错的方法,使用最小公共分母,更具体地说,是提供了对其所有子类的最佳抽象的异常类。

考虑以下方法声明:

public String encrypt(String plainText) 
    throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
        UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException,
        UnsupportedEncodingException  {
    // 方法体
}

对所有这些异常进行更仔细的检查,可以发现它们都扩展自 GeneralSecurityException。因此,你可以重构上述代码如下:

public String encrypt(String plainText) throws GeneralSecurityException,
    UnsupportedEncodingException  {
    // 方法体
}

唯一一个没有继承 GeneralSecurityException 的异常是 UnsupportedEncodingException,因此你必须显式声明它。

从客户端的角度考虑:你更愿意使用哪个版本?

try {
    String encrypted = cipher.encrypt("Test");
} catch(InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException
        | UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException e) {
    // 无法加密
} catch(UnsupportedEncodingException e) {
    // 错误的编码
}
try {
    String encrypted = cipher.encrypt("Test");
} catch(GeneralSecurityException e) {
    // 无法加密
} catch(UnsupportedEncodingException e) {
    // 错误的编码
}
英文:

It is always a good apprach to use the least common denominator, or more specific, the exception class that provides the best abstraction over all of its descendents.

Consider the following method declaration:

public String encrypt(String plainText) 
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException,
UnsupportedEncodingException  {
// body
}

A closer inspection of all those exceptions reveals that all of them extend GeneralSecurityException. Therefore, you can refactor the above code as:

public String encrypt(String plainText) throws GeneralSecurityException,
UnsupportedEncodingException  {
// body
}

The only exception, which does not inherit GeneralSecurityException, is UnsupportedEncodingException so you have to explicitly declare it.

Think of it from the client side: Which version would you rather use?

try {
String encrypted = cipher.encrypt(&quot;Test&quot;);
} catch(InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException
| UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException e) {
// cannot encrypt
} catch(UnsupportedEncodingException e) {
// wrong encoding
}
try {
String encrypted = cipher.encrypt(&quot;Test&quot;);
} catch(GeneralSecurityException e) {
// cannot encrypt
} catch(UnsupportedEncodingException e) {
// wrong encoding
}

huangapple
  • 本文由 发表于 2020年8月19日 19:54:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/63486425.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定