java - 将 Joda 日期与用户名结合作为单个变量进行加密

标签 java spring-mvc encryption jodatime

我正在 Spring-MVC 应用程序中工作,对于密码重置功能,我正在发送一封电子邮件,其中包含用户名+Joda 日期。在发送之前,我想以可以完美反转的方式对内容(日期+用户名)进行加密。就我的理论理解而言,逆向不是首先就违背了加密的目的吗?如果没有,那么我想对它们进行加密,然后使用某种机制来解密它们。我找到了一些解决方案,其中一个提到检索,但我无法弄清楚哪个实体是哪个。我粘贴下面的代码。请看一下:

加密和解密:

byte[] userBytes = username.getBytes("UTF-8");
byte[] keyBytes = key.getBytes("UTF-8");
//XOR scramble
byte[] encrypted = new byte[userBytes.length];
for(int i = 0; i < userBytes.length; i++){
   encrypted[i] = (byte)(userBytes[i] ^ keyBytes[i % keyBytes.length]);
}

BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(encrypted);

// webappB, decode the parameter
BASE64Decoder decoder = new BASE64Decoder();
byte[] decoded =  decoder.decodeBuffer( encoded );
//XOR descramble
byte[] decrypted = new byte[decoded.length];
for(int i = 0; i < decoded.length; i++){
   decrypted[i] = (byte)(decoded[i] ^ keyBytes[i % keyBytes.length] );
}

最佳答案

此类有两个公共(public)方法,一个用于生成 token ,另一个用于验证 token 。它是从更大、更复杂的代码中删减的,因此可能会引入一些错误。还嵌入了一些测试,因此您可以立即使用它。无论如何,我希望这足以让您走上正轨。

package tokens;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class TokenUtils {

    private static final String HMAC_ALGO = "HmacSHA256";
    private static final String TOKEN_SEPARATOR = ":";
    private static final long MAX_AGE = 1_000 * 60 * 60 * 24; // 24h

    private TokenUtils() {
    }

    public static String createToken(String username, long timestamp, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
        StringBuilder sb = new StringBuilder();
        sb.append(generateTokenStringPublicPart(username, timestamp));
        sb.append(TOKEN_SEPARATOR);
        sb.append(computeSignature(username, timestamp, secretKey));
        return sb.toString();
    }

    public static boolean verifyToken(String token, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
        String[] parts = token.split(TOKEN_SEPARATOR);
        boolean result = false;
        if (parts.length == 3) {
            String username = parts[0];
            Long timestamp = Long.valueOf(parts[1]);
            String signature = parts[2];
            if (signature.equals(computeSignature(username, timestamp, secretKey))) {
                if (System.currentTimeMillis() - timestamp < MAX_AGE) {
                    result = true;
                }
            }
        }
        return result;
    }

    private static String generateTokenStringPublicPart(String username, long timestamp) {
        StringBuilder sb = new StringBuilder();
        sb.append(username);
        sb.append(TOKEN_SEPARATOR);
        sb.append(timestamp);
        return sb.toString();
    }

    private static String computeSignature(String username, long timestamp, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
        StringBuilder sb = new StringBuilder();
        sb.append(generateTokenStringPublicPart(username, timestamp));
        SecretKeySpec sks = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), HMAC_ALGO);
        Mac hmac = Mac.getInstance(HMAC_ALGO);
        hmac.init(sks);
        return Base64.getUrlEncoder().encodeToString(hmac.doFinal(sb.toString().getBytes(StandardCharsets.UTF_8)));
    }

    public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
        String secretKey = "secret_key";
        String token = TokenUtils.createToken("marko", System.currentTimeMillis(), secretKey);
        System.out.println(token);
        System.out.println("Original token verification: " + TokenUtils.verifyToken(token, secretKey));
        token = token.replaceAll("a", "b");
        System.out.println("Tampered token verification: " + TokenUtils.verifyToken(token, secretKey));
        token = TokenUtils.createToken("marko", System.currentTimeMillis() - 1_000 * 60 * 60 * 48, secretKey);
        System.out.println("Expired token verification: " + TokenUtils.verifyToken(token, secretKey));
    }

}

关于java - 将 Joda 日期与用户名结合作为单个变量进行加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27039986/

相关文章:

java - Android 中针对 Salesforce Web 服务的 SSL 证书问题

java - 将maven项目导入到eclipse中

c - OpenSSL 调试 - 如何在 openssl 中转储中间 ASN.1?

与此 ColdFusion Decrypt 函数等效的 C#

java - 当rebel.load_embedded_plugins设置为false时,如何在JRebel中热部署.jsp?

java - 公历

java - 在其 ViewPager 中使用带有 ScrollView 的 fragment 隐藏选项卡式 Activity 中的工具栏

java - 更新查询以更改依赖于其他表的一个表中的文件

Java MVC ActionListener NullPointerException

python - 在写入消息时对其进行加密