如何在 Java 中加密字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1205135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:53:23  来源:igfitidea点击:

How to encrypt String in Java

javaencryption

提问by ante.sabo

What I need is to encrypt string which will show up in 2D barcode(PDF-417) so when someone get an idea to scan it will get nothing readable.

我需要的是加密将显示在 2D 条形码(PDF-417)中的字符串,这样当有人想扫描它时,它将无法读取。

Other requirements:

其他需求:

  • should not be complicated
  • it should not consist of RSA, PKI infrastructure, key pairs, etc.
  • 不应该复杂
  • 它不应包含 RSA、PKI 基础设施、密钥对等。

It must be simple enough to get rid of the people snooping around, and easy to decrypt for other companies interested in getting that data. They call us, we tell them the standard or give them some simple key which can then be used for decryption.

它必须足够简单,才能摆脱四处窥探的人,并且对于有兴趣获取这些数据的其他公司来说也很容易解密。他们打电话给我们,我们告诉他们标准或给他们一些简单的密钥,然后可以用于解密。

Probably those companies could use different technologies so it would be good to stick to some standard which is not tied to some special platform or technology.

可能这些公司可以使用不同的技术,因此最好坚持一些与某些特殊平台或技术无关的标准。

What do you suggest? Is there some Java class doing encrypt()& decrypt()without much complication in achieving high security standards?

你有什么建议?有一些Java类做encrypt()decrypt()没有太多的并发症,实现高安全标准?

采纳答案by ante.sabo

Warning

Do not use this as some kind of security measurement.

The encryption mechanism in this post is a One-time pad, which means that the secret key can be easily recovered by an attacker using 2 encrypted messages. XOR 2 encrypted messages and you get the key. That simple!

Pointed out by Moussa

警告

不要将此用作某种安全度量。

这篇文章中的加密机制是一次性密码,这意味着攻击者可以使用 2 条加密消息轻松恢复密钥。XOR 2 加密消息,您将获得密钥。就这么简单!

穆萨指出



I am using Sun's Base64Encoder/Decoder which is to be found in Sun's JRE, to avoid yet another JAR in lib. That's dangerous from point of using OpenJDK or some other's JRE. Besides that, is there another reason I should consider using Apache commons lib with Encoder/Decoder?

我正在使用 Sun 的 Base64Encoder/Decoder,它可以在 Sun 的 JRE 中找到,以避免在 lib 中出现另一个 JAR。从使用 OpenJDK 或其他一些 JRE 的角度来看,这是危险的。除此之外,还有另一个原因我应该考虑将 Apache commons lib 与编码器/解码器一起使用吗?

public class EncryptUtils {
    public static final String DEFAULT_ENCODING = "UTF-8"; 
    static BASE64Encoder enc = new BASE64Encoder();
    static BASE64Decoder dec = new BASE64Decoder();

    public static String base64encode(String text) {
        try {
            return enc.encode(text.getBytes(DEFAULT_ENCODING));
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }//base64encode

    public static String base64decode(String text) {
        try {
            return new String(dec.decodeBuffer(text), DEFAULT_ENCODING);
        } catch (IOException e) {
            return null;
        }
    }//base64decode

    public static void main(String[] args) {
        String txt = "some text to be encrypted";
        String key = "key phrase used for XOR-ing";
        System.out.println(txt + " XOR-ed to: " + (txt = xorMessage(txt, key)));

        String encoded = base64encode(txt);       
        System.out.println(" is encoded to: " + encoded + " and that is decoding to: " + (txt = base64decode(encoded)));
        System.out.print("XOR-ing back to original: " + xorMessage(txt, key));
    }

    public static String xorMessage(String message, String key) {
        try {
            if (message == null || key == null) return null;

            char[] keys = key.toCharArray();
            char[] mesg = message.toCharArray();

            int ml = mesg.length;
            int kl = keys.length;
            char[] newmsg = new char[ml];

            for (int i = 0; i < ml; i++) {
                newmsg[i] = (char)(mesg[i] ^ keys[i % kl]);
            }//for i

            return new String(newmsg);
        } catch (Exception e) {
            return null;
        }
    }//xorMessage
}//class

回答by Markus Lausberg

Here are some links you can read what Java supports

这里有一些链接,您可以阅读 Java 支持的内容

Encrypting/decrypting a data stream.

加密/解密数据流。

This example demonstrates how to encrypt (using a symmetric encryption algorithm such as AES, Blowfish, RC2, 3DES, etc) a large amount of data. The data is passed in chunks to one of the encrypt methods: EncryptBytes, EncryptString, EncryptBytesENC, or EncryptStringENC. (The method name indicates the type of input (string or byte array) and the return type (encoded string or byte array). The FirstChunk and LastChunk properties are used to indicate whether a chunk is the first, middle, or last in a stream to be encrypted. By default, both FirstChunk and LastChunk equal true -- meaning that the data passed is the entire amount.

此示例演示如何加密(使用对称加密算法,例如 AES、Blowfish、RC2、3DES 等)大量数据。数据以块的形式传递到加密方法之一:EncryptBytes、EncryptString、EncryptBytesENC 或 EncryptStringENC。(方法名指示输入类型(字符串或字节数组)和返回类型(编码字符串或字节数组)。FirstChunk 和 LastChunk 属性用于指示块是流中的第一个、中间或最后一个被加密。默认情况下,FirstChunk 和 LastChunk 都等于真——这意味着传递的数据是全部数量。

JCERefGuide

JCE参考指南

Java Encryption Examples

Java 加密示例

回答by VoidPointer

I'd recommend to use some standard symmetric cypher that is widely available like DES, 3DESor AES. While that is not the most secure algorithm, there are loads of implementations and you'd just need to give the key to anyone that is supposed to decrypt the information in the barcode. javax.crypto.Cipheris what you want to work with here.

我建议使用一些广泛使用的标准对称密码,如DES3DESAES。虽然这不是最安全的算法,但有很多实现,您只需要将密钥提供给任何应该解密条形码信息的人。javax.crypto.Cipher是你想要在这里使用的东西。

Let's assume the bytes to encrypt are in

让我们假设要加密的字节在

byte[] input;

Next, you'll need the key and initialization vectorbytes

接下来,您将需要密钥和初始化向量字节

byte[] keyBytes;
byte[] ivBytes;

Now you can initialize the Cipher for the algorithm that you select:

现在您可以为您选择的算法初始化密码:

// wrap key data in Key/IV specs to pass to cipher
SecretKeySpec key = new SecretKeySpec(keyBytes, "DES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
// create the cipher with the algorithm you choose
// see javadoc for Cipher class for more info, e.g.
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

Encryption would go like this:

加密将是这样的:

cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted= new byte[cipher.getOutputSize(input.length)];
int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);

And decryption like this:

和解密是这样的:

cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0);
dec_len += cipher.doFinal(decrypted, dec_len);

回答by sherif

thanks ive made this class using your code maybe someone finds it userfull

谢谢我使用你的代码制作了这个课程,也许有人觉得它很有用

object crypter

对象密码器

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class ObjectCrypter {

private Cipher deCipher;
private Cipher enCipher;
private SecretKeySpec key;
private IvParameterSpec ivSpec;


public ObjectCrypter(byte[] keyBytes,   byte[] ivBytes) {
    // wrap key data in Key/IV specs to pass to cipher


     ivSpec = new IvParameterSpec(ivBytes);
    // create the cipher with the algorithm you choose
    // see javadoc for Cipher class for more info, e.g.
    try {
         DESKeySpec dkey = new  DESKeySpec(keyBytes);
          key = new SecretKeySpec(dkey.getKey(), "DES");
         deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
         enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public byte[] encrypt(Object obj) throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, IllegalBlockSizeException, ShortBufferException, BadPaddingException {
    byte[] input = convertToByteArray(obj);
    enCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

    return enCipher.doFinal(input);




//  cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
//  byte[] encypted = new byte[cipher.getOutputSize(input.length)];
//  int enc_len = cipher.update(input, 0, input.length, encypted, 0);
//  enc_len += cipher.doFinal(encypted, enc_len);
//  return encypted;


}
public Object decrypt( byte[]  encrypted) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException {
    deCipher.init(Cipher.DECRYPT_MODE, key, ivSpec);

    return convertFromByteArray(deCipher.doFinal(encrypted));

}



private Object convertFromByteArray(byte[] byteObject) throws IOException,
        ClassNotFoundException {
    ByteArrayInputStream bais;

    ObjectInputStream in;
    bais = new ByteArrayInputStream(byteObject);
    in = new ObjectInputStream(bais);
    Object o = in.readObject();
    in.close();
    return o;

}



private byte[] convertToByteArray(Object complexObject) throws IOException {
    ByteArrayOutputStream baos;

    ObjectOutputStream out;

    baos = new ByteArrayOutputStream();

    out = new ObjectOutputStream(baos);

    out.writeObject(complexObject);

    out.close();

    return baos.toByteArray();

}


}

回答by yegor256

How about this:

这个怎么样:

private static byte[] xor(final byte[] input, final byte[] secret) {
    final byte[] output = new byte[input.length];
    if (secret.length == 0) {
        throw new IllegalArgumentException("empty security key");
    }
    int spos = 0;
    for (int pos = 0; pos < input.length; ++pos) {
        output[pos] = (byte) (input[pos] ^ secret[spos]);
        ++spos;
        if (spos >= secret.length) {
            spos = 0;
        }
    }
    return output;
}

Works fine for me and is rather compact.

对我来说很好用,而且相当紧凑。

回答by rishikesh

public static String encryptParams(String myTextInput) {

        String myKey = "40674244454045cb9a70040a30e1c007";
        String myVector = "@1B2c3D4e5F6g7H8";

        String encData = "";

        try{
            JavaEncryprtionUtil encUtil = new JavaEncryprtionUtil();
            encData = Base64.encodeToString(encUtil.encrypt(myTextInput.getBytes("UTF-8"), myKey.getBytes("UTF-8"), myVector.getBytes("UTF-8")),Base64.DEFAULT);
            System.out.println(encData);
        }catch(NoSuchAlgorithmException ex){
            ex.printStackTrace();
        }catch(NoSuchPaddingException ex){
            ex.printStackTrace();
        }catch(InvalidKeyException ex){
            ex.printStackTrace();
        }catch(InvalidAlgorithmParameterException ex){
            ex.printStackTrace();
        }catch(IllegalBlockSizeException ex){
            ex.printStackTrace();
        }catch(BadPaddingException ex){
            ex.printStackTrace();
        }catch(UnsupportedEncodingException ex){
            ex.printStackTrace();
        }

        return encData;
    }

回答by hdost

I would consider using something like https://www.bouncycastle.org/It is a prebuilt library that allows you to encrypt whatever you like with a number of different Ciphers I understand that you only want to protect from snooping, but if you really want to protect the information, using Base64 won't actually protect you.

我会考虑使用类似https://www.bouncycastle.org/ 之类的东西,它是一个预构建的库,允许您使用多种不同的密码加密您喜欢的任何内容我知道您只想防止窥探,但如果您真的想要保护信息,使用 Base64 实际上不会保护你。

回答by hdost

Here's my implementation from meta64.com as a Spring Singleton. If you want to create a ciper instance for each call that would work also, and then you could remove the 'synchronized' calls, but beware 'cipher' is not thread-safe.

这是我从 meta64.com 实现的 Spring Singleton。如果您想为每个也可以工作的调用创建一个 ciper 实例,然后您可以删除“同步”调用,但要注意“密码”不是线程安全的。

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class Encryptor {

    @Value("${aeskey}")
    private String keyStr;

    private Key aesKey = null;
    private Cipher cipher = null;

    synchronized private void init() throws Exception {
        if (keyStr == null || keyStr.length() != 16) {
            throw new Exception("bad aes key configured");
        }
        if (aesKey == null) {
            aesKey = new SecretKeySpec(keyStr.getBytes(), "AES");
            cipher = Cipher.getInstance("AES");
        }
    }

    synchronized public String encrypt(String text) throws Exception {
        init();
        cipher.init(Cipher.ENCRYPT_MODE, aesKey);
        return toHexString(cipher.doFinal(text.getBytes()));
    }

    synchronized public String decrypt(String text) throws Exception {
        init();
        cipher.init(Cipher.DECRYPT_MODE, aesKey);
        return new String(cipher.doFinal(toByteArray(text)));
    }

    public static String toHexString(byte[] array) {
        return DatatypeConverter.printHexBinary(array);
    }

    public static byte[] toByteArray(String s) {
        return DatatypeConverter.parseHexBinary(s);
    }

    /*
     * DO NOT DELETE
     * 
     * Use this commented code if you don't like using DatatypeConverter dependency
     */
    // public static String toHexStringOld(byte[] bytes) {
    // StringBuilder sb = new StringBuilder();
    // for (byte b : bytes) {
    // sb.append(String.format("%02X", b));
    // }
    // return sb.toString();
    // }
    //
    // public static byte[] toByteArrayOld(String s) {
    // int len = s.length();
    // byte[] data = new byte[len / 2];
    // for (int i = 0; i < len; i += 2) {
    // data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i +
    // 1), 16));
    // }
    // return data;
    // }
}

回答by Bartosz Wójcik

You might want to consider some automated tool to do the encryption / decryption code generation eg. https://www.stringencrypt.com/java-encryption/

您可能需要考虑使用一些自动化工具来生成加密/解密代码,例如。https://www.stringencrypt.com/java-encryption/

It can generate different encryption and decryption code each time for the string or file encryption.

它可以为字符串或文件加密每次生成不同的加密和解密代码。

It's pretty handy when it comes to fast string encryption without using RSA, AES etc.

在不使用 RSA、AES 等的情况下进行快速字符串加密时,它非常方便。

Sample results:

示例结果:

// encrypted with https://www.stringencrypt.com (v1.1.0) [Java]
// szTest = "Encryption in Java!"
String szTest = "\u9E3F\uA60F\uAE07\uB61B\uBE1F\uC62B\uCE2D\uD611" +
                "\uDE03\uE5FF\uEEED\uF699\uFE3D\u071C\u0ED2\u1692" +
                "\u1E06\u26AE\u2EDC";

for (int iatwS = 0, qUJQG = 0; iatwS < 19; iatwS++)
{
        qUJQG = szTest.charAt(iatwS);
        qUJQG ++;
        qUJQG = ((qUJQG << 5) | ( (qUJQG & 0xFFFF) >> 11)) & 0xFFFF;
        qUJQG -= iatwS;
        qUJQG = (((qUJQG & 0xFFFF) >> 6) | (qUJQG << 10)) & 0xFFFF;
        qUJQG ^= iatwS;
        qUJQG -= iatwS;
        qUJQG = (((qUJQG & 0xFFFF) >> 3) | (qUJQG << 13)) & 0xFFFF;
        qUJQG ^= 0xFFFF;
        qUJQG ^= 0xB6EC;
        qUJQG = ((qUJQG << 8) | ( (qUJQG & 0xFFFF) >> 8)) & 0xFFFF;
        qUJQG --;
        qUJQG = (((qUJQG & 0xFFFF) >> 5) | (qUJQG << 11)) & 0xFFFF;
        qUJQG ++;
        qUJQG ^= 0xFFFF;
        qUJQG += iatwS;
        szTest = szTest.substring(0, iatwS) + (char)(qUJQG & 0xFFFF) + szTest.substring(iatwS + 1);
}

System.out.println(szTest);

We use it all the time in our company.

我们一直在公司使用它。

回答by Kamil Nekanowicz

You can use Jasypt

您可以使用Jasypt

With Jasypt, encrypting and checking a password can be as simple as...

使用 Jasypt,加密和检查密码就像...

StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
textEncryptor.setPassword(myEncryptionPassword);

Encryption:

加密:

String myEncryptedText = textEncryptor.encrypt(myText);

Decryption:

解密:

String plainText = textEncryptor.decrypt(myEncryptedText);

Gradle:

摇篮:

compile group: 'org.jasypt', name: 'jasypt', version: '1.9.2'

Features:

特征:

Jasypt provides you with easy unidirectional (digest) and bidirectional encryption techniques.

Open API for use with any JCE provider, and not only the default Java VM one. Jasypt can be easily used with well-known providers like Bouncy Castle. Learn more.

Higher security for your users' passwords. Learn more.

Binary encryption support. Jasypt allows the digest and encryption of binaries (byte arrays). Encrypt your objects or files when needed (for being sent over the net, for example).

Number encryption support. Besides texts and binaries, it allows the digest and encryption of numeric values (BigInteger and BigDecimal, other numeric types are supported when encrypting for Hibernate persistence). Learn more.

Completely thread-safe.

Support for encryptor/digester pooling, in order to achieve high performance in multi-processor/multi-core systems.

Includes a lightweight ("lite") version of the library for better manageability in size-restrictive environments like mobile platforms.

Provides both easy, no-configuration encryption tools for users new to encryption, and also highly configurable standard encryption tools, for power-users.

Hibernate 3 and 4 optional integration for persisting fields of your mapped entities in an encrypted manner. Encryption of fields is defined in the Hibernate mapping files, and it remains transparent for the rest of the application (useful for sensitive personal data, databases with many read-enabled users...). Encrypt texts, binaries, numbers, booleans, dates... Learn more.

Seamlessly integrable into a Spring application, with specific integration features for Spring 2, Spring 3.0 and Spring 3.1. All the digesters and encryptors in jasypt are designed to be easily used (instantiated, dependency-injected...) from Spring. And, because of their being thread-safe, they can be used without synchronization worries in a singleton-oriented environment like Spring. Learn more: Spring 2, Spring 3.0, Spring 3.1.

Spring Security (formerly Acegi Security) optional integration for performing password encryption and matching tasks for the security framework, improving the security of your users' passwords by using safer password encryption mechanisms and providing you with a higher degree of configuration and control. Learn more.

Provides advanced functionality for encrypting all or part of an application's configuration files, including sensitive information like database passwords. Seamlessly integrate encrypted configuration into plain, Spring-based and/or Hibernate-enabled applications. Learn more.

Provides easy to use CLI (Command Line Interface) tools to allow developers initialise their encrypted data and include encryption/decryption/digest operations in maintenance tasks or scripts. Learn more.

Integrates into Apache Wicket, for more robust encryption of URLs in your secure applications.

Comprehensive guides and javadoc documentation, to allow developers to better understand what they are really doing to their data.

Robust charset support, designed to adequately encrypt and digest texts whichever the original charset is. Complete support for languages like Japanese, Korean, Arabic... with no encoding or platform issues.

Very high level of configuration capabilities: The developer can implement tricks like instructing an "encryptor" to ask a, for example, remote HTTPS server for the password to be used for encryption. It lets you meet your security needs.

Jasypt 为您提供简单的单向(摘要)和双向加密技术。

用于任何 JCE 提供程序的开放 API,而不仅仅是默认的 Java VM 提供程序。Jasypt 可以很容易地与 Bouncy Castle 等知名提供商一起使用。了解更多。

为您的用户密码提供更高的安全性。了解更多。

二进制加密支持。Jasypt 允许对二进制文件(字节数组)进行摘要和加密。在需要时加密您的对象或文件(例如通过网络发送)。

号码加密支持。除了文本和二进制文件,它还允许对数值进行摘要和加密(BigInteger 和 BigDecimal,加密 Hibernate 持久性时支持其他数字类型)。了解更多。

完全线程安全。

支持加密器/摘要器池,以在多处理器/多核系统中实现高性能。

包括库的轻量级(“精简”)版本,以便在移动平台等大小受限的环境中具有更好的可管理性。

为加密新手提供简单、无需配置的加密工具,也为高级用户提供高度可配置的标准加密工具。

Hibernate 3 和 4 可选集成,用于以加密方式持久化映射实体的字段。字段加密在 Hibernate 映射文件中定义,它对应用程序的其余部分保持透明(对于敏感的个人数据、具有许多已启用读取的用户的数据库......)。加密文本、二进制文件、数字、布尔值、日期……了解更多。

无缝集成到 Spring 应用程序中,具有适用于 Spring 2、Spring 3.0 和 Spring 3.1 的特定集成功能。jasypt 中的所有摘要器和加密器都设计为易于从 Spring 使用(实例化、依赖注入...)。而且,由于它们是线程安全的,它们可以在像 Spring 这样的面向单例的环境中使用而无需担心同步问题。了解更多:Spring 2、Spring 3.0、Spring 3.1。

Spring Security(原Acegi Security)可选集成,用于为安全框架执行密码加密和匹配任务,通过使用更安全的密码加密机制来提高用户密码的安全性,并为您提供更高程度的配置和控制。了解更多。

提供用于加密全部或部分应用程序配置文件的高级功能,包括数据库密码等敏感信息。将加密配置无缝集成到普通的、基于 Spring 的和/或支持 Hibernate 的应用程序中。了解更多。

提供易于使用的 CLI(命令行界面)工具,允许开发人员初始化他们的加密数据,并在维护任务或脚本中包含加密/解密/摘要操作。了解更多。

集成到 Apache Wicket 中,以在您的安全应用程序中对 URL 进行更强大的加密。

全面的指南和 javadoc 文档,使开发人员能够更好地了解他们真正对数据做了什么。

强大的字符集支持,旨在充分加密和消化文本,无论原始字符集是什么。完全支持日语、韩语、阿拉伯语等语言,没有编码或平台问题。

非常高级的配置功能:开发人员可以实施一些技巧,例如指示“加密器”向远程 HTTPS 服务器询问用于加密的密码。它可以让您满足您的安全需求。