6

我有一个用 Java 编码的 base64 编码字符串:

string s = "x8QeoAdVOAwpKHAeXIxEticayZLMx7RP_baVdSpDSLLea5TZMxRT-IX93lA05MEUzmwtOvd6WLRBluLchZz2EJSHsFfxxtPQF1VEFv4rA5w="

我正在尝试使用以下语句在 C# 中对其进行解码。

string s = "x8QeoAdVOAwpKHAeXIxEticayZLMx7RP_baVdSpDSLLea5TZMxRT-IX93lA05MEUzmwtOvd6WLRBluLchZz2EJSHsFfxxtPQF1VEFv4rA5w="

var decodedBytes = System.Convert.FromBase64String(s);

但我得到了错误:

输入不是有效的 Base-64 字符串,因为它包含非 base 64 字符、两个以上的填充字符或填充字符中的非法字符。

我究竟做错了什么?我可以清楚地看到没有非法字符。谁能指出我正确的方向?

更新:这是生成该字符串的 java 代码。

 private static String encrypt(byte[] iv, String salt, String password, String clearText) throws Exception {
byte[] encryptedBytes = encryptDecrypt(true, iv, salt, password, clearText.getBytes("UTF-8"));
return Base64.encodeBytes(encryptedBytes, 16);

}

  private static byte[] encryptDecrypt(boolean encrypt, byte[] iv, String salt, String password, byte[] bytesToEncryptDecrypt) throws Exception {
SecretKeySpec secretKeySpec = null;
MessageDigest digester = MessageDigest.getInstance("SHA-1");
digester.update((salt + password).getBytes("UTF-8"));
byte[] key = digester.digest();
secretKeySpec = new SecretKeySpec(key, 2, 16, "AES");
IvParameterSpec ivps = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(encrypt ? 1 : 2, secretKeySpec, ivps);
return cipher.doFinal(bytesToEncryptDecrypt, 0, bytesToEncryptDecrypt.length);

}

这是 Base64.class 文件(反编译)。它具有来自 Java 的编码和解码方法。

public class Base64
{
  public static final int NO_OPTIONS = 0;
  public static final int ENCODE = 1;
  public static final int DECODE = 0;
  public static final int GZIP = 2;
  public static final int DONT_GUNZIP = 4;
  public static final int DO_BREAK_LINES = 8;
  public static final int URL_SAFE = 16;
  public static final int ORDERED = 32;
  private static final int MAX_LINE_LENGTH = 76;
  private static final byte EQUALS_SIGN = 61;
  private static final byte NEW_LINE = 10;
  private static final String PREFERRED_ENCODING = "US-ASCII";
  private static final byte WHITE_SPACE_ENC = -5;
  private static final byte EQUALS_SIGN_ENC = -1;
  private static final byte[] _STANDARD_ALPHABET = { 
    65, 66, 67, 68, 69, 70, 71, 
    72, 73, 74, 75, 76, 77, 78, 
    79, 80, 81, 82, 83, 84, 85, 
    86, 87, 88, 89, 90, 
    97, 98, 99, 100, 101, 102, 103, 
    104, 105, 106, 107, 108, 109, 110, 
    111, 112, 113, 114, 115, 116, 117, 
    118, 119, 120, 121, 122, 
    48, 49, 50, 51, 52, 53, 
    54, 55, 56, 57, 43, 47 };

  private static final byte[] _STANDARD_DECODABET = { 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -5, -5, 
    -9, -9, 
    -5, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, 
    -5, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    62, 
    -9, -9, -9, 
    63, 
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 
    -9, -9, -9, 
    -1, 
    -9, -9, -9, 
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
    14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 
    -9, -9, -9, -9, -9, -9, 
    26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 
    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 
    -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9 };

  private static final byte[] _URL_SAFE_ALPHABET = { 
    65, 66, 67, 68, 69, 70, 71, 
    72, 73, 74, 75, 76, 77, 78, 
    79, 80, 81, 82, 83, 84, 85, 
    86, 87, 88, 89, 90, 
    97, 98, 99, 100, 101, 102, 103, 
    104, 105, 106, 107, 108, 109, 110, 
    111, 112, 113, 114, 115, 116, 117, 
    118, 119, 120, 121, 122, 
    48, 49, 50, 51, 52, 53, 
    54, 55, 56, 57, 45, 95 };

  private static final byte[] _URL_SAFE_DECODABET = { 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -5, -5, 
    -9, -9, 
    -5, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, 
    -5, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, 
    -9, 
    62, 
    -9, 
    -9, 
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 
    -9, -9, -9, 
    -1, 
    -9, -9, -9, 
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
    14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 
    -9, -9, -9, -9, 
    63, 
    -9, 
    26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 
    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 
    -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9 };

  private static final byte[] _ORDERED_ALPHABET = { 
    45, 
    48, 49, 50, 51, 52, 
    53, 54, 55, 56, 57, 
    65, 66, 67, 68, 69, 70, 71, 
    72, 73, 74, 75, 76, 77, 78, 
    79, 80, 81, 82, 83, 84, 85, 
    86, 87, 88, 89, 90, 
    95, 
    97, 98, 99, 100, 101, 102, 103, 
    104, 105, 106, 107, 108, 109, 110, 
    111, 112, 113, 114, 115, 116, 117, 
    118, 119, 120, 121, 122 };

  private static final byte[] _ORDERED_DECODABET = { 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -5, -5, 
    -9, -9, 
    -5, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, 
    -5, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, 
    -9, 
    0, -9, 
    -9, 
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
    -9, -9, -9, 
    -1, 
    -9, -9, -9, 
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 
    24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 
    -9, -9, -9, -9, 
    37, 
    -9, 
    38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 
    51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 
    -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 
    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9 };

  private static final byte[] getAlphabet(int options)
  {
    if ((options & 0x10) == 16)
      return _URL_SAFE_ALPHABET;
    if ((options & 0x20) == 32) {
      return _ORDERED_ALPHABET;
    }
    return _STANDARD_ALPHABET;
  }

  private static final byte[] getDecodabet(int options)
  {
    if ((options & 0x10) == 16)
      return _URL_SAFE_DECODABET;
    if ((options & 0x20) == 32) {
      return _ORDERED_DECODABET;
    }
    return _STANDARD_DECODABET;
  }

  private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes, int options)
  {
    encode3to4(threeBytes, 0, numSigBytes, b4, 0, options);
    return b4;
  }

  private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset, int options)
  {
    byte[] ALPHABET = getAlphabet(options);

    int inBuff = (numSigBytes > 0 ? source[srcOffset] << 24 >>> 8 : 0) | (
      numSigBytes > 1 ? source[(srcOffset + 1)] << 24 >>> 16 : 0) | (
      numSigBytes > 2 ? source[(srcOffset + 2)] << 24 >>> 24 : 0);

    switch (numSigBytes)
    {
    case 3:
      destination[destOffset] = ALPHABET[(inBuff >>> 18)];
      destination[(destOffset + 1)] = ALPHABET[(inBuff >>> 12 & 0x3F)];
      destination[(destOffset + 2)] = ALPHABET[(inBuff >>> 6 & 0x3F)];
      destination[(destOffset + 3)] = ALPHABET[(inBuff & 0x3F)];
      return destination;
    case 2:
      destination[destOffset] = ALPHABET[(inBuff >>> 18)];
      destination[(destOffset + 1)] = ALPHABET[(inBuff >>> 12 & 0x3F)];
      destination[(destOffset + 2)] = ALPHABET[(inBuff >>> 6 & 0x3F)];
      destination[(destOffset + 3)] = 61;
      return destination;
    case 1:
      destination[destOffset] = ALPHABET[(inBuff >>> 18)];
      destination[(destOffset + 1)] = ALPHABET[(inBuff >>> 12 & 0x3F)];
      destination[(destOffset + 2)] = 61;
      destination[(destOffset + 3)] = 61;
      return destination;
    }

    return destination;
  }

  public static void encode(ByteBuffer raw, ByteBuffer encoded)
  {
    byte[] raw3 = new byte[3];
    byte[] enc4 = new byte[4];

    while (raw.hasRemaining()) {
      int rem = Math.min(3, raw.remaining());
      raw.get(raw3, 0, rem);
      encode3to4(enc4, raw3, rem, 0);
      encoded.put(enc4);
    }
  }

  public static void encode(ByteBuffer raw, CharBuffer encoded)
  {
    byte[] raw3 = new byte[3];
    byte[] enc4 = new byte[4];
    int i;
    for (; raw.hasRemaining(); 
      i < 4)
    {
      int rem = Math.min(3, raw.remaining());
      raw.get(raw3, 0, rem);
      encode3to4(enc4, raw3, rem, 0);
      i = 0; continue;
      encoded.put((char)(enc4[i] & 0xFF));

      i++;
    }
  }

  public static String encodeObject(Serializable serializableObject)
    throws IOException
  {
    return encodeObject(serializableObject, 0);
  }

  public static String encodeObject(Serializable serializableObject, int options)
    throws IOException
  {
    if (serializableObject == null) {
      throw new NullPointerException("Cannot serialize a null object.");
    }

    ByteArrayOutputStream baos = null;
    OutputStream b64os = null;
    GZIPOutputStream gzos = null;
    ObjectOutputStream oos = null;
    try
    {
      baos = new ByteArrayOutputStream();
      b64os = new OutputStream(baos, 0x1 | options);
      if ((options & 0x2) != 0)
      {
        gzos = new GZIPOutputStream(b64os);
        oos = new ObjectOutputStream(gzos);
      }
      else {
        oos = new ObjectOutputStream(b64os);
      }
      oos.writeObject(serializableObject);
    }
    catch (IOException e)
    {
      throw e;
    } finally {
      try {
        oos.close(); } catch (Exception localException) {
      }try { gzos.close(); } catch (Exception localException1) {
      }try { b64os.close(); } catch (Exception localException2) {
      }try { baos.close();
      } catch (Exception localException3) {
      }
    }
    try {
      return new String(baos.toByteArray(), "US-ASCII");
    }
    catch (UnsupportedEncodingException uue) {
    }
    return new String(baos.toByteArray());
  }

  public static String encodeBytes(byte[] source)
  {
    String encoded = null;
    try {
      encoded = encodeBytes(source, 0, source.length, 0);
    } catch (IOException ex) {
      if (!$assertionsDisabled) throw new AssertionError(ex.getMessage());
    }
    assert (encoded != null);
    return encoded;
  }

  public static String encodeBytes(byte[] source, int options)
    throws IOException
  {
    return encodeBytes(source, 0, source.length, options);
  }

  public static String encodeBytes(byte[] source, int off, int len)
  {
    String encoded = null;
    try {
      encoded = encodeBytes(source, off, len, 0);
    } catch (IOException ex) {
      if (!$assertionsDisabled) throw new AssertionError(ex.getMessage());
    }
    assert (encoded != null);
    return encoded;
  }

  public static String encodeBytes(byte[] source, int off, int len, int options)
    throws IOException
  {
    byte[] encoded = encodeBytesToBytes(source, off, len, options);
    try
    {
      return new String(encoded, "US-ASCII");
    } catch (UnsupportedEncodingException uue) {
    }
    return new String(encoded);
  }

  public static byte[] encodeBytesToBytes(byte[] source)
  {
    byte[] encoded = (byte[])null;
    try {
      encoded = encodeBytesToBytes(source, 0, source.length, 0);
    } catch (IOException ex) {
      if (!$assertionsDisabled) throw new AssertionError("IOExceptions only come from GZipping, which is turned off: " + ex.getMessage());
    }
    return encoded;
  }

  public static byte[] encodeBytesToBytes(byte[] source, int off, int len, int options)
    throws IOException
  {
    if (source == null) {
      throw new NullPointerException("Cannot serialize a null array.");
    }

    if (off < 0) {
      throw new IllegalArgumentException("Cannot have negative offset: " + off);
    }

    if (len < 0) {
      throw new IllegalArgumentException("Cannot have length offset: " + len);
    }

    if (off + len > source.length) {
      throw new IllegalArgumentException(
        String.format("Cannot have offset of %d and length of %d with array of length %d", new Object[] { Integer.valueOf(off), Integer.valueOf(len), Integer.valueOf(source.length) }));
    }

    if ((options & 0x2) != 0) {
      ByteArrayOutputStream baos = null;
      GZIPOutputStream gzos = null;
      OutputStream b64os = null;
      try
      {
        baos = new ByteArrayOutputStream();
        b64os = new OutputStream(baos, 0x1 | options);
        gzos = new GZIPOutputStream(b64os);

        gzos.write(source, off, len);
        gzos.close();
      }
      catch (IOException e)
      {
        throw e;
      } finally {
        try {
          gzos.close(); } catch (Exception localException) {
        }try { b64os.close(); } catch (Exception localException1) {
        }try { baos.close(); } catch (Exception localException2) {
        }
      }
      return baos.toByteArray();
    }

    boolean breakLines = (options & 0x8) != 0;

    int encLen = len / 3 * 4 + (len % 3 > 0 ? 4 : 0);
    if (breakLines) {
      encLen += encLen / 76;
    }
    byte[] outBuff = new byte[encLen];

    int d = 0;
    int e = 0;
    int len2 = len - 2;
    int lineLength = 0;
    for (; d < len2; e += 4) {
      encode3to4(source, d + off, 3, outBuff, e, options);

      lineLength += 4;
      if ((breakLines) && (lineLength >= 76))
      {
        outBuff[(e + 4)] = 10;
        e++;
        lineLength = 0;
      }
      d += 3;
    }

    if (d < len) {
      encode3to4(source, d + off, len - d, outBuff, e, options);
      e += 4;
    }

    if (e <= outBuff.length - 1)
    {
      byte[] finalOut = new byte[e];
      System.arraycopy(outBuff, 0, finalOut, 0, e);

      return finalOut;
    }

    return outBuff;
  }

  private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset, int options)
  {
    if (source == null) {
      throw new NullPointerException("Source array was null.");
    }
    if (destination == null) {
      throw new NullPointerException("Destination array was null.");
    }
    if ((srcOffset < 0) || (srcOffset + 3 >= source.length)) {
      throw new IllegalArgumentException(String.format(
        "Source array with length %d cannot have offset of %d and still process four bytes.", new Object[] { Integer.valueOf(source.length), Integer.valueOf(srcOffset) }));
    }
    if ((destOffset < 0) || (destOffset + 2 >= destination.length)) {
      throw new IllegalArgumentException(String.format(
        "Destination array with length %d cannot have offset of %d and still store three bytes.", new Object[] { Integer.valueOf(destination.length), Integer.valueOf(destOffset) }));
    }

    byte[] DECODABET = getDecodabet(options);

    if (source[(srcOffset + 2)] == 61)
    {
      int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | 
        (DECODABET[source[(srcOffset + 1)]] & 0xFF) << 12;

      destination[destOffset] = ((byte)(outBuff >>> 16));
      return 1;
    }

    if (source[(srcOffset + 3)] == 61)
    {
      int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | 
        (DECODABET[source[(srcOffset + 1)]] & 0xFF) << 12 | 
        (DECODABET[source[(srcOffset + 2)]] & 0xFF) << 6;

      destination[destOffset] = ((byte)(outBuff >>> 16));
      destination[(destOffset + 1)] = ((byte)(outBuff >>> 8));
      return 2;
    }

    int outBuff = (DECODABET[source[srcOffset]] & 0xFF) << 18 | 
      (DECODABET[source[(srcOffset + 1)]] & 0xFF) << 12 | 
      (DECODABET[source[(srcOffset + 2)]] & 0xFF) << 6 | 
      DECODABET[source[(srcOffset + 3)]] & 0xFF;

    destination[destOffset] = ((byte)(outBuff >> 16));
    destination[(destOffset + 1)] = ((byte)(outBuff >> 8));
    destination[(destOffset + 2)] = ((byte)outBuff);

    return 3;
  }

  public static byte[] decode(byte[] source)
    throws IOException
  {
    byte[] decoded = (byte[])null;

    decoded = decode(source, 0, source.length, 0);

    return decoded;
  }

  public static byte[] decode(byte[] source, int off, int len, int options)
    throws IOException
  {
    if (source == null) {
      throw new NullPointerException("Cannot decode null source array.");
    }
    if ((off < 0) || (off + len > source.length)) {
      throw new IllegalArgumentException(String.format(
        "Source array with length %d cannot have offset of %d and process %d bytes.", new Object[] { Integer.valueOf(source.length), Integer.valueOf(off), Integer.valueOf(len) }));
    }

    if (len == 0)
      return new byte[0];
    if (len < 4) {
      throw new IllegalArgumentException(
        "Base64-encoded string must have at least four characters, but length specified was " + len);
    }

    byte[] DECODABET = getDecodabet(options);

    int len34 = len * 3 / 4;
    byte[] outBuff = new byte[len34];
    int outBuffPosn = 0;

    byte[] b4 = new byte[4];
    int b4Posn = 0;
    int i = 0;
    byte sbiDecode = 0;

    for (i = off; i < off + len; i++)
    {
      sbiDecode = DECODABET[(source[i] & 0xFF)];

      if (sbiDecode >= -5)
      {
        byte[] out;
        if (sbiDecode >= -1) {
          b4[(b4Posn++)] = source[i];
          if (b4Posn > 3) {
            outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, options);
            b4Posn = 0;

            if (source[i] == 61) {
              break;
            }
          }
        }
      }
      else
      {
        throw new IOException(String.format(
          "Bad Base64 input character decimal %d in array position %d", new Object[] { Integer.valueOf(source[i] & 0xFF), Integer.valueOf(i) }));
      }
    }

    out = new byte[outBuffPosn];
    System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
    return out;
  }

  public static byte[] decode(String s)
    throws IOException
  {
    return decode(s, 0);
  }

  public static byte[] decode(String s, int options)
    throws IOException
  {
    if (s == null) {
      throw new NullPointerException("Input string was null.");
    }

    try
    {
      bytes = s.getBytes("US-ASCII");
    }
    catch (UnsupportedEncodingException uee)
    {
      byte[] bytes;
      bytes = s.getBytes();
    }

    byte[] bytes = decode(bytes, 0, bytes.length, options);

    boolean dontGunzip = (options & 0x4) != 0;
    if ((bytes != null) && (bytes.length >= 4) && (!dontGunzip))
    {
      int head = bytes[0] & 0xFF | bytes[1] << 8 & 0xFF00;
      if (35615 == head) {
        ByteArrayInputStream bais = null;
        GZIPInputStream gzis = null;
        ByteArrayOutputStream baos = null;
        byte[] buffer = new byte[2048];
        int length = 0;
        try
        {
          baos = new ByteArrayOutputStream();
          bais = new ByteArrayInputStream(bytes);
          gzis = new GZIPInputStream(bais);

          while ((length = gzis.read(buffer)) >= 0) {
            baos.write(buffer, 0, length);
          }

          bytes = baos.toByteArray();
        }
        catch (IOException e)
        {
          e.printStackTrace();
          try
          {
            baos.close(); } catch (Exception localException) {
          }try { gzis.close(); } catch (Exception localException1) {
          }try { bais.close(); }
          catch (Exception localException2)
          {
          }
        }
        finally
        {
          try
          {
            baos.close(); } catch (Exception localException3) {
          }try { gzis.close(); } catch (Exception localException4) {
          }try { bais.close();
          } catch (Exception localException5) {
          }
        }
      }
    }
    return bytes;
  }

  public static Object decodeToObject(String encodedObject)
    throws IOException, ClassNotFoundException
  {
    return decodeToObject(encodedObject, 0, null);
  }

}
4

2 回答 2

7

它应该像用C# 使用的and替换Java 使用的-and一样简单:_+/

string s = "Vv7JKbNHOvHxC4L89be4vNw-J0KKPkMlq4iZb_T-35u-kjYhilF_ECJAPVufv2-2_ynUORVkIPPqd1H7MC-mrWW7Fu4ZcmsHG2Q1gJOU=";
string corrected = s.Replace('-', '+').Replace('_', '/');
var decodedBytes = System.Convert.FromBase64String(corrected);

但是,您的示例字符串似乎也不正确;它有 105 个字符长,但(因为它被填充)长度应该是 4 的倍数。如果你=从输入中删除尾随,那么这段代码就可以工作,但我会担心它是如何到达那里的。如果它应该在那里,您需要以编程方式修剪/填充您的输入,然后仔细检查您获得的结果是否符合您的预期。

于 2012-12-18T08:32:01.673 回答
0

试试这个代码:(注意:这个代码还没有针对性能进行优化,因为它使用了字符串连接)

using System;
namespace Crypto
{
    public class Base64
    {
        private const String STANDARD_FIRST_62_CHARS=
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"+
                "abcdefghijklmnopqrstuvwxyz"+
                "0123456789";

        public const String STANDARD_RADIX_STRING=
                STANDARD_FIRST_62_CHARS + "+/";

        public const String RFC4648_RADIX_STRING=
                STANDARD_FIRST_62_CHARS + "-_";

        private const char padding='=';
        private char[]radix_chars;

        public Base64(String radix_string)
        {
            radix_chars=radix_string.ToCharArray();
        }

        public Base64():this(STANDARD_RADIX_STRING)
        {
        }

        public String decode(String str)
        {
            String binary_str = "";
            char[]chars = str.ToCharArray();
            int i=0;
            for(;i<chars.Length && chars[i]!=padding;++i)
            {
                int index = indexOf(chars[i]);
                String bin_of_index = DecimalToBinary(index,6);
                binary_str = binary_str + bin_of_index;
            }
            binary_str = binary_str.Substring(0,binary_str.Length - (2*(chars.Length-i)));
            str = "";
            for(i = 0 ; i < binary_str.Length ; i = i+8)
            {
                String bin_str = binary_str.Substring(i,8);
                int char_point = Convert.ToInt16(bin_str,2);
                str = str + ((char)char_point);
            }
            return str;
        }

        public String encode(String str)
        {
            // TODO
            return null;
        }

        private String DecimalToBinary(int value,int length)
        {
            String bin_string = Convert.ToString(value, 2);
            length = length - bin_string.Length;
            while(length > 0 )
            {
                bin_string = "0"+bin_string;
                --length;
            }
            return bin_string;
        }

        private int indexOf(char c)
        {
            for(int index=0; index < radix_chars.Length ; ++ index)
                if(c == radix_chars[index])
                    return index;
            return -1;
        }
    }
}
public class Program
{
    public static void Main()
    {
        Crypto.Base64 b = new Crypto.Base64(Crypto.Base64.RFC4648_RADIX_STRING);
        Console.WriteLine(b.decode("x8QeoAdVOAwpKHAeXIxEticayZLMx7RP_baVdSpDSLLea5TZMxRT-IX93lA05MEUzmwtOvd6WLRBluLchZz2EJSHsFfxxtPQF1VEFv4rA5w="));
    }
}

如果您希望decode方法返回 abyte[]而不是String然后将decode方法更改为:

        public byte[] decode(String str)
        {
            String binary_str = "";
            char[]chars = str.ToCharArray();
            int i=0;
            for(;i<chars.Length && chars[i]!=padding;++i)
            {
                int index = indexOf(chars[i]);
                String bin_of_index = DecimalToBinary(index,6);
                binary_str = binary_str + bin_of_index;
            }
            binary_str = binary_str.Substring(0,binary_str.Length - (2*(chars.Length-i)));
            byte[]bytes=new byte[binary_str.Length/8];
            for(i = 0 ; i < binary_str.Length ; i = i+8)
            {
                String bin_str = binary_str.Substring(i,8);
                int char_point = Convert.ToInt16(bin_str,2);
                bytes[i/8] = (byte) char_point;
            }
            return bytes;
        }
于 2012-12-18T11:03:37.777 回答