加密字符串以匹配原始字符串的长度
Encrypt a string to match length of original string
我需要一个简单的 c# 算法,它将一个包含 x 个字符的字符串 'encrypt' 转换为另一个也包含 x 个字符的字符串。它不一定是安全的,但不应该通过简单地查看加密字符串来重建原始字符串。例如,如果我输入 "hello",我应该得到类似 "x=w3q" 的结果。它不应该简单地将每个角色映射到其他东西,但它不必比这复杂得多。它需要是对称的,所以我需要能够从 "x=w3q".
构造 "hello"
到目前为止,我已经尝试过 RijndaelManaged 和 RSA 加密,但加密后的字符串比原始字符串长很多。
有什么想法吗?
你可以根据字符的索引映射到不同的字符,这样就不那么明显了。
private static readonly int[] charOffsets = new[]{30,26,39,...};
private static char EncryptChar(char c, int index)
{
return (char)(c + charOffests[index % charOffsets.Length]);
}
private static char DecryptChar(char c, int index)
{
return (char)(c - charOffests[index % charOffsets.Length]);
}
public static string Encrypt(string str)
{
return new string(str.Select((c, i) => EncryptChar(c, i)));
}
public static string Decrypt(string str)
{
return new string(str.Select((c, i) => DecryptChar(c, i)));
}
如果您只需要字母字符等,您可以稍微调整一下。但我希望您明白了。
您可以开始使用 ROT13 算法,然后根据前一个字符更改偏移量。
示例:"hello"
'h' 的 ROT13 --> 'u'
由于 U 是字母表中的第 21 个字母,接下来您将使用 ROT21:
'e' 的 ROT8 --> 'z'
等等。
这不仅可以保持长度不变,还可以处理额外的字符,只要您将它们添加到字母表中即可。
如果现在还不够清楚,我深表歉意,我还在 phone。
编辑:
这是一些代码,这会更有意义:
static String alphabet = "abcdefghijklmnopqrstuvwxyz";
public static String encrypt(String originalString)
{
String returnString = "";
int shift = alphabet.Length / 2;
foreach (char c in originalString)
{
int nextIndex = alphabet.IndexOf(c) + shift;
if (nextIndex > alphabet.Length)
nextIndex = nextIndex - alphabet.Length;
returnString += alphabet[nextIndex];
shift = alphabet.IndexOf(alphabet[nextIndex]);
}
return returnString;
}
public static String decrypt(String encryptedString)
{
String returnString = "";
int shift = alphabet.Length / 2;
foreach (char c in encryptedString)
{
int nextIndex = alphabet.IndexOf(c) - shift;
if (nextIndex < 0)
nextIndex = alphabet.Length + nextIndex; // nextIndex is negative so we are decreasing regardless
returnString += alphabet[nextIndex];
shift = alphabet.IndexOf(c);
}
return returnString;
}
字母表可以随心所欲地扩展。不安全,但是很简单,不是光看一眼就能轻易破译的
一种选择是使用经典密码,例如 Vigenère. If you are prepared to accept bytes, rather than readable characters, then RC4 是一种更现代的选择。
Vigenère 和 RC4 都是不安全的,对于商业级加密来说也不安全。为此你需要 AES。对于相同的输出长度,您可以在 CTR 模式下尝试 AES,但在这种情况下您需要分别发送密钥和随机数。
如果你想要一个众所周知的(经典的)密码,这里有一个 Vigenère 的实现。
import java.util.EnumSet;
import java.util.Set;
/**
* Simple object oriented implementation of the classical Vigenère cipher.
* Note that Vigenère is - of course - not considered secure anymore.
*
* @author maartenb
*/
public class Vigenère {
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final int LA = ALPHABET.length();
/**
* Flags to be used for the Vigenère cipher.
*/
public enum Flag {
/**
* Do not encrypt/decrypt space characters but leave them in the same
* position.
*/
SKIP_SPACE;
}
private enum State {
INSTANTIATED, INITIALIZED;
}
private enum Operation {
ENCRYPT, DECRYPT;
public int direction() {
switch (this) {
case ENCRYPT:
return 1;
case DECRYPT:
return -1;
default:
throw new IllegalStateException();
}
}
}
private State state = State.INSTANTIATED;
private String key;
private int lk;
private Set<Flag> flags;
/**
* Initializes the cipher with the given key.
*
* @param key
* the key that can only use the characters in the alphabet
* @param flags
* option flag parameters
* @throws IllegalArgumentException
* if the key contains invalid characters
*/
public void init(final String key, final Set<Flag> flags) {
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Key null or empty");
}
this.lk = key.length();
for (int i = 0; i < this.lk; i++) {
if (ALPHABET.indexOf(key.codePointAt(i)) == -1) {
throw new IllegalArgumentException("Key character nat index "
+ i + " not in alphabet");
}
}
this.key = key;
this.flags = flags;
this.state = State.INITIALIZED;
}
/**
* Encrypts the plaintext using the key set during initialization.
*
* @param plaintext
* the plaintext, using the characters in the alphabet
* @return the ciphertext
* @throws IllegalStateException
* if the cipher wasn't initialized
* @throws IllegalArgumentException
* if the plaintext contains characters not in the alphabet
*/
public String encrypt(final String plaintext) {
if (this.state != State.INITIALIZED) {
throw new IllegalStateException("Not initialized");
}
return crypt(plaintext, Operation.ENCRYPT);
}
/**
* Decrypts the ciphertext using the key set during initialization.
*
* @param ciphertext
* the ciphertext, using the characters in the alphabet
* @return the plaintext
* @throws IllegalStateException
* if the cipher wasn't initialized
* @throws IllegalArgumentException
* if the ciphertext contains characters not in the alphabet
*/
public String decrypt(final String ciphertext) {
if (this.state != State.INITIALIZED) {
throw new IllegalStateException("Not initialized");
}
return crypt(ciphertext, Operation.DECRYPT);
}
private String crypt(final String in, final Operation op)
throws IllegalStateException, IllegalArgumentException {
final StringBuilder out = new StringBuilder(in.length());
// legend: c = character, k = key, o = offset, in = input, out = output
int skipped = 0;
for (int ino = 0; ino < in.length(); ino++) {
// get character (code point in Unicode)
final int inc = in.codePointAt(ino);
// skip space, if configured
if (inc == ' ' && this.flags.contains(Flag.SKIP_SPACE)) {
out.appendCodePoint(' ');
skipped++;
continue;
}
// get matching key character
final int kc = this.key.codePointAt(mod(ino - skipped, this.lk));
final int kco = ALPHABET.indexOf(kc);
final int inco = ALPHABET.indexOf(inc);
if (inco == -1) {
throw new IllegalArgumentException(
"Invalid character at offset " + ino);
}
// the main calculation
final int outco = mod(inco + op.direction() * kco, LA);
final int outc = ALPHABET.codePointAt(outco);
out.appendCodePoint(outc);
}
return out.toString();
}
private static int mod(final int x, final int n) {
// note that % is the remainder operation in Java
// so it doesn't handle negative values correctly
return (x % n + n) % n;
}
/**
* Main method for testing purposes only.
*
* @param args
* ignored
*/
public static void main(final String[] args) {
// example taken from Wikipedia page on Vigenère
final Vigenère vigenere = new Vigenère();
vigenere.init("LEMON", EnumSet.of(Vigenère.Flag.SKIP_SPACE));
final String ct = vigenere.encrypt("ATTACK AT DAWN");
System.out.println(ct);
final String pt = vigenere.decrypt(ct);
System.out.println(pt);
}
}
我需要一个简单的 c# 算法,它将一个包含 x 个字符的字符串 'encrypt' 转换为另一个也包含 x 个字符的字符串。它不一定是安全的,但不应该通过简单地查看加密字符串来重建原始字符串。例如,如果我输入 "hello",我应该得到类似 "x=w3q" 的结果。它不应该简单地将每个角色映射到其他东西,但它不必比这复杂得多。它需要是对称的,所以我需要能够从 "x=w3q".
构造 "hello"到目前为止,我已经尝试过 RijndaelManaged 和 RSA 加密,但加密后的字符串比原始字符串长很多。
有什么想法吗?
你可以根据字符的索引映射到不同的字符,这样就不那么明显了。
private static readonly int[] charOffsets = new[]{30,26,39,...};
private static char EncryptChar(char c, int index)
{
return (char)(c + charOffests[index % charOffsets.Length]);
}
private static char DecryptChar(char c, int index)
{
return (char)(c - charOffests[index % charOffsets.Length]);
}
public static string Encrypt(string str)
{
return new string(str.Select((c, i) => EncryptChar(c, i)));
}
public static string Decrypt(string str)
{
return new string(str.Select((c, i) => DecryptChar(c, i)));
}
如果您只需要字母字符等,您可以稍微调整一下。但我希望您明白了。
您可以开始使用 ROT13 算法,然后根据前一个字符更改偏移量。
示例:"hello"
'h' 的 ROT13 --> 'u'
由于 U 是字母表中的第 21 个字母,接下来您将使用 ROT21:
'e' 的 ROT8 --> 'z'
等等。
这不仅可以保持长度不变,还可以处理额外的字符,只要您将它们添加到字母表中即可。
如果现在还不够清楚,我深表歉意,我还在 phone。
编辑:
这是一些代码,这会更有意义:
static String alphabet = "abcdefghijklmnopqrstuvwxyz";
public static String encrypt(String originalString)
{
String returnString = "";
int shift = alphabet.Length / 2;
foreach (char c in originalString)
{
int nextIndex = alphabet.IndexOf(c) + shift;
if (nextIndex > alphabet.Length)
nextIndex = nextIndex - alphabet.Length;
returnString += alphabet[nextIndex];
shift = alphabet.IndexOf(alphabet[nextIndex]);
}
return returnString;
}
public static String decrypt(String encryptedString)
{
String returnString = "";
int shift = alphabet.Length / 2;
foreach (char c in encryptedString)
{
int nextIndex = alphabet.IndexOf(c) - shift;
if (nextIndex < 0)
nextIndex = alphabet.Length + nextIndex; // nextIndex is negative so we are decreasing regardless
returnString += alphabet[nextIndex];
shift = alphabet.IndexOf(c);
}
return returnString;
}
字母表可以随心所欲地扩展。不安全,但是很简单,不是光看一眼就能轻易破译的
一种选择是使用经典密码,例如 Vigenère. If you are prepared to accept bytes, rather than readable characters, then RC4 是一种更现代的选择。
Vigenère 和 RC4 都是不安全的,对于商业级加密来说也不安全。为此你需要 AES。对于相同的输出长度,您可以在 CTR 模式下尝试 AES,但在这种情况下您需要分别发送密钥和随机数。
如果你想要一个众所周知的(经典的)密码,这里有一个 Vigenère 的实现。
import java.util.EnumSet;
import java.util.Set;
/**
* Simple object oriented implementation of the classical Vigenère cipher.
* Note that Vigenère is - of course - not considered secure anymore.
*
* @author maartenb
*/
public class Vigenère {
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final int LA = ALPHABET.length();
/**
* Flags to be used for the Vigenère cipher.
*/
public enum Flag {
/**
* Do not encrypt/decrypt space characters but leave them in the same
* position.
*/
SKIP_SPACE;
}
private enum State {
INSTANTIATED, INITIALIZED;
}
private enum Operation {
ENCRYPT, DECRYPT;
public int direction() {
switch (this) {
case ENCRYPT:
return 1;
case DECRYPT:
return -1;
default:
throw new IllegalStateException();
}
}
}
private State state = State.INSTANTIATED;
private String key;
private int lk;
private Set<Flag> flags;
/**
* Initializes the cipher with the given key.
*
* @param key
* the key that can only use the characters in the alphabet
* @param flags
* option flag parameters
* @throws IllegalArgumentException
* if the key contains invalid characters
*/
public void init(final String key, final Set<Flag> flags) {
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Key null or empty");
}
this.lk = key.length();
for (int i = 0; i < this.lk; i++) {
if (ALPHABET.indexOf(key.codePointAt(i)) == -1) {
throw new IllegalArgumentException("Key character nat index "
+ i + " not in alphabet");
}
}
this.key = key;
this.flags = flags;
this.state = State.INITIALIZED;
}
/**
* Encrypts the plaintext using the key set during initialization.
*
* @param plaintext
* the plaintext, using the characters in the alphabet
* @return the ciphertext
* @throws IllegalStateException
* if the cipher wasn't initialized
* @throws IllegalArgumentException
* if the plaintext contains characters not in the alphabet
*/
public String encrypt(final String plaintext) {
if (this.state != State.INITIALIZED) {
throw new IllegalStateException("Not initialized");
}
return crypt(plaintext, Operation.ENCRYPT);
}
/**
* Decrypts the ciphertext using the key set during initialization.
*
* @param ciphertext
* the ciphertext, using the characters in the alphabet
* @return the plaintext
* @throws IllegalStateException
* if the cipher wasn't initialized
* @throws IllegalArgumentException
* if the ciphertext contains characters not in the alphabet
*/
public String decrypt(final String ciphertext) {
if (this.state != State.INITIALIZED) {
throw new IllegalStateException("Not initialized");
}
return crypt(ciphertext, Operation.DECRYPT);
}
private String crypt(final String in, final Operation op)
throws IllegalStateException, IllegalArgumentException {
final StringBuilder out = new StringBuilder(in.length());
// legend: c = character, k = key, o = offset, in = input, out = output
int skipped = 0;
for (int ino = 0; ino < in.length(); ino++) {
// get character (code point in Unicode)
final int inc = in.codePointAt(ino);
// skip space, if configured
if (inc == ' ' && this.flags.contains(Flag.SKIP_SPACE)) {
out.appendCodePoint(' ');
skipped++;
continue;
}
// get matching key character
final int kc = this.key.codePointAt(mod(ino - skipped, this.lk));
final int kco = ALPHABET.indexOf(kc);
final int inco = ALPHABET.indexOf(inc);
if (inco == -1) {
throw new IllegalArgumentException(
"Invalid character at offset " + ino);
}
// the main calculation
final int outco = mod(inco + op.direction() * kco, LA);
final int outc = ALPHABET.codePointAt(outco);
out.appendCodePoint(outc);
}
return out.toString();
}
private static int mod(final int x, final int n) {
// note that % is the remainder operation in Java
// so it doesn't handle negative values correctly
return (x % n + n) % n;
}
/**
* Main method for testing purposes only.
*
* @param args
* ignored
*/
public static void main(final String[] args) {
// example taken from Wikipedia page on Vigenère
final Vigenère vigenere = new Vigenère();
vigenere.init("LEMON", EnumSet.of(Vigenère.Flag.SKIP_SPACE));
final String ct = vigenere.encrypt("ATTACK AT DAWN");
System.out.println(ct);
final String pt = vigenere.decrypt(ct);
System.out.println(pt);
}
}