我需要一个简单的c#算法,该算法需要一串x个字符并加密'它到另一个x字符串。它不必是安全的,但是通过简单地查看加密的字符串来重建原始字符串是不可能的。例如,如果我输入" hello",我应该得到类似" x = w3q"的东西。它不应该简单地将每个角色映射到其他角色,但它并不比这复杂得多。它需要是对称的,所以我需要能够构建"你好"来自" x = w3q"。
到目前为止,我已尝试过RijndaelManaged和RSA加密,但加密后的字符串比原始字符串要长很多。
有什么想法吗?
答案 0 :(得分:4)
您可以使用ROT13算法开始,然后根据前一个字符更改偏移量。
示例:“你好”
'h'的ROT13 - > 'U'
由于U是字母表中的第21个字母,您接下来将使用ROT21:
'e'的ROT8 - > 'z'
等等。
这样不仅可以保持长度不变,还可以处理额外的字符,只要将它们添加到字母表即可。
如果现在还不够清楚,我道歉,我正在打电话。
修改强>
这是一些代码,这将更有意义:
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;
}
可以根据需要扩展字母表。这不安全,但它很简单,只要看一下就不能轻易破译。
答案 1 :(得分:2)
如果您想要一个众所周知的(经典)密码,这里是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);
}
}
答案 2 :(得分:1)
您可以根据角色的索引映射到不同的角色,这样就不那么明显了。
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)));
}
如果你只想要字母字符等,你可以稍微调整它。但是你希望得到这个想法。
答案 3 :(得分:0)