码迷,mamicode.com
首页 > 编程语言 > 详细

C# Java 3DES加密解密 扩展及修正\0 问题

时间:2014-11-29 21:41:11      阅读:496      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   ar   color   os   sp   

 

注: C#已亲测及做扩展, Java 部分未做验证

/// <summary>
/// 3DES加密解密
/// -----------------------------------------------------------
/// 说明:
/// 转载自网上http://bbs.csdn.net/topics/350158619
/// 并加以扩展
/// 修正:
/// 1. 修改正解密后出现 ‘\0‘
/// 注: 1. 向量不能小于8位
/// 2. 明文末尾如果是带‘\0‘字符,则会一起去掉
/// -----------------------------------------------------------
/// 扩展人:Wuyf    11222337#qq.com
/// 日 期:2014-11-29
/// </summary>

 

C# 代码 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.IO;
  4 using System.Linq;
  5 using System.Security.Cryptography;
  6 using System.Text;
  7 using System.Web;
  8 
  9 namespace WuFrame.Tool
 10 {
 11 
 12     /// <summary>
 13     /// 3DES加密解密
 14     /// -----------------------------------------------------------
 15     /// 说明:
 16     ///     转载自网上http://bbs.csdn.net/topics/350158619
 17     ///     并加以扩展
 18     /// 修正:
 19     ///     1. 修改正解密后出现 ‘\0‘
 20     /// 注: 1. 向量不能小于8位
 21     ///     2. 明文末尾如果是带‘\0‘字符,则会一起去掉
 22     /// -----------------------------------------------------------
 23     /// 扩展人:Wuyf 11222337#qq.com
 24     /// 日  期:2014-11-29
 25     /// </summary>
 26     public class Des3Tool
 27     {
 28         #region CBC模式**
 29 
 30         #region 扩展方法
 31         
 32         /// <summary>
 33         /// 3DES 加密(字符串参数和返回值)
 34         /// </summary>
 35         /// <param name="key">密钥</param>
 36         /// <param name="iv">向量</param>
 37         /// <param name="data">明文</param>
 38         /// <param name="isRetBase64">true:返回base64,false:返回Utf8</param>
 39         /// <returns></returns>
 40         public static string Des3EncodeCBC(string key, string iv, string data)
 41         {
 42             string rtnResult = string.Empty;
 43             byte[] rtnValue = null;
 44             byte[] keyArr = Encoding.UTF8.GetBytes(key);
 45             byte[] ivArr = Encoding.UTF8.GetBytes(iv);
 46             byte[] dataArr = Encoding.UTF8.GetBytes(data);
 47 
 48             rtnValue = Des3EncodeCBC(keyArr, ivArr, dataArr);
 49 
 50             rtnResult = Convert.ToBase64String(rtnValue);
 51 
 52             return rtnResult;
 53         }
 54 
 55         /// <summary>
 56         /// 3DES 解密(字符串参数和返回值)
 57         /// </summary>
 58         /// <param name="key">密钥</param>
 59         /// <param name="iv">向量</param>
 60         /// <param name="data">明文</param>
 61         /// <returns></returns>
 62         public static string Des3DecodeCBC(string key, string iv, string dataEnBase64)
 63         {
 64             string rtnResult = string.Empty;
 65             byte[] rtnValue = null;
 66             byte[] keyArr = Encoding.UTF8.GetBytes(key);
 67             byte[] ivArr = Encoding.UTF8.GetBytes(iv);
 68             byte[] dataArr = Convert.FromBase64String(dataEnBase64);
 69 
 70             rtnValue = Des3DecodeCBC(keyArr, ivArr, dataArr);
 71 
 72             rtnResult = Encoding.UTF8.GetString(rtnValue).TrimEnd(\0);    // 去除多余空字符
 73 
 74             return rtnResult;
 75         }
 76 
 77         /// <summary>
 78         /// 3DES 解密(字符串参数和返回值)
 79         /// </summary>
 80         /// <param name="key">密钥</param>
 81         /// <param name="iv">向量</param>
 82         /// <param name="data">明文</param>
 83         /// <returns></returns>
 84         public static string Des3DecodeCBC(string key, string iv, byte[] dataArr)
 85         {
 86             string rtnResult = string.Empty;
 87             byte[] rtnValue = null;
 88             byte[] keyArr = Encoding.UTF8.GetBytes(key);
 89             byte[] ivArr = Encoding.UTF8.GetBytes(iv);
 90 
 91             rtnValue = Des3DecodeCBC(keyArr, ivArr, dataArr);
 92 
 93             rtnResult = Encoding.UTF8.GetString(rtnValue).TrimEnd(\0);    // 去除多余空字符
 94 
 95             return rtnResult;
 96         }
 97 
 98         #endregion
 99 
100         #region 原加解密方法
101         
102 
103         /// <summary>
104         /// DES3 CBC模式加密
105         /// </summary>
106         /// <param name="key">密钥</param>
107         /// <param name="iv">IV</param>
108         /// <param name="data">明文的byte数组</param>
109         /// <returns>密文的byte数组</returns>
110         public static byte[] Des3EncodeCBC(byte[] key, byte[] iv, byte[] data)
111         {
112             //复制于MSDN
113 
114             try
115             {
116                 // Create a MemoryStream.
117                 MemoryStream mStream = new MemoryStream();
118 
119                 TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
120                 tdsp.Mode = CipherMode.CBC;             //默认值
121                 tdsp.Padding = PaddingMode.PKCS7;       //默认值
122 
123                 // Create a CryptoStream using the MemoryStream 
124                 // and the passed key and initialization vector (IV).
125                 CryptoStream cStream = new CryptoStream(mStream,
126                     tdsp.CreateEncryptor(key, iv),
127                     CryptoStreamMode.Write);
128 
129                 // Write the byte array to the crypto stream and flush it.
130                 cStream.Write(data, 0, data.Length);
131                 cStream.FlushFinalBlock();
132 
133                 // Get an array of bytes from the 
134                 // MemoryStream that holds the 
135                 // encrypted data.
136                 byte[] ret = mStream.ToArray();
137 
138                 // Close the streams.
139                 cStream.Close();
140                 mStream.Close();
141 
142                 // Return the encrypted buffer.
143                 return ret;
144             }
145             catch (CryptographicException e)
146             {
147                 Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
148                 return null;
149             }
150         }
151 
152         /// <summary>
153         /// DES3 CBC模式解密
154         /// </summary>
155         /// <param name="key">密钥</param>
156         /// <param name="iv">IV</param>
157         /// <param name="data">密文的byte数组</param>
158         /// <returns>明文的byte数组</returns>
159         public static byte[] Des3DecodeCBC(byte[] key, byte[] iv, byte[] data)
160         {
161             try
162             {
163                 // Create a new MemoryStream using the passed 
164                 // array of encrypted data.
165                 MemoryStream msDecrypt = new MemoryStream(data);
166 
167                 TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
168                 tdsp.Mode = CipherMode.CBC;
169                 tdsp.Padding = PaddingMode.PKCS7;
170 
171                 // Create a CryptoStream using the MemoryStream 
172                 // and the passed key and initialization vector (IV).
173                 CryptoStream csDecrypt = new CryptoStream(msDecrypt,
174                     tdsp.CreateDecryptor(key, iv),
175                     CryptoStreamMode.Read);
176 
177                 // Create buffer to hold the decrypted data.
178                 byte[] fromEncrypt = new byte[data.Length];
179 
180                 // Read the decrypted data out of the crypto stream
181                 // and place it into the temporary buffer.
182                 csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
183 
184                 //Convert the buffer into a string and return it.
185                 return fromEncrypt;
186             }
187             catch (CryptographicException e)
188             {
189                 Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
190                 return null;
191             }
192         }
193 
194         #endregion
195 
196         #endregion
197 
198         #region ECB模式
199 
200         #region 不提供Iv(扩展方法)
201 
202         private static string ivDefault = "12345678";
203 
204         /// <summary>
205         /// 3DES 加密(字符串参数和返回值)
206         /// </summary>
207         /// <param name="key">密钥</param>
208         /// <param name="iv">向量</param>
209         /// <param name="data">明文</param>
210         /// <param name="isRetBase64">true:返回base64,false:返回Utf8</param>
211         /// <returns></returns>
212         public static string Des3EncodeECB(string key, string data)
213         {
214             string rtnResult = string.Empty;
215             byte[] rtnValue = null;
216             byte[] keyArr = Encoding.UTF8.GetBytes(key);
217             byte[] ivArr = Encoding.UTF8.GetBytes(ivDefault);
218             byte[] dataArr = Encoding.UTF8.GetBytes(data);
219 
220             rtnValue = Des3EncodeCBC(keyArr, ivArr, dataArr);
221 
222             rtnResult = Convert.ToBase64String(rtnValue);
223 
224             return rtnResult;
225         }
226 
227         /// <summary>
228         /// 3DES 解密(字符串参数和返回值)
229         /// </summary>
230         /// <param name="key">密钥</param>
231         /// <param name="iv">向量</param>
232         /// <param name="data">明文</param>
233         /// <returns></returns>
234         public static string Des3DecodeECB(string key, string dataEnBase64)
235         {
236             string rtnResult = string.Empty;
237             byte[] rtnValue = null;
238             byte[] keyArr = Encoding.UTF8.GetBytes(key);
239             byte[] ivArr = Encoding.UTF8.GetBytes(ivDefault);
240             byte[] dataArr = Convert.FromBase64String(dataEnBase64);
241 
242             rtnValue = Des3DecodeCBC(keyArr, ivArr, dataArr);
243 
244             rtnResult = Encoding.UTF8.GetString(rtnValue).TrimEnd(\0);    // 去除多余空字符
245 
246             return rtnResult;
247         }
248 
249         /// <summary>
250         /// 3DES 解密(字符串参数和返回值)
251         /// </summary>
252         /// <param name="key">密钥</param>
253         /// <param name="iv">向量</param>
254         /// <param name="data">明文</param>
255         /// <returns></returns>
256         public static string Des3DecodeECB(string key, byte[] dataArr)
257         {
258             string rtnResult = string.Empty;
259             byte[] rtnValue = null;
260             byte[] keyArr = Encoding.UTF8.GetBytes(key);
261             byte[] ivArr = Encoding.UTF8.GetBytes(ivDefault);
262 
263             rtnValue = Des3DecodeECB(keyArr, ivArr, dataArr);
264 
265             rtnResult = Encoding.UTF8.GetString(rtnValue).TrimEnd(\0);    // 去除多余空字符
266 
267             return rtnResult;
268         }
269         #endregion
270 
271         #region 提供Iv(扩展方法)
272 
273 
274         /// <summary>
275         /// 3DES 加密(字符串参数和返回值)
276         /// </summary>
277         /// <param name="key">密钥</param>
278         /// <param name="iv">向量</param>
279         /// <param name="data">明文</param>
280         /// <param name="isRetBase64">true:返回base64,false:返回Utf8</param>
281         /// <returns></returns>
282         public static string Des3EncodeECB(string key, string iv, string data)
283         {
284             string rtnResult = string.Empty;
285             byte[] rtnValue = null;
286             byte[] keyArr = Encoding.UTF8.GetBytes(key);
287             byte[] ivArr = Encoding.UTF8.GetBytes(iv);
288             byte[] dataArr = Encoding.UTF8.GetBytes(data);
289 
290             rtnValue = Des3EncodeCBC(keyArr, ivArr, dataArr);
291 
292             rtnResult = Convert.ToBase64String(rtnValue);
293 
294             return rtnResult;
295         }
296 
297         /// <summary>
298         /// 3DES 解密(字符串参数和返回值)
299         /// </summary>
300         /// <param name="key">密钥</param>
301         /// <param name="iv">向量</param>
302         /// <param name="data">明文</param>
303         /// <returns></returns>
304         public static string Des3DecodeECB(string key, string iv, string dataEnBase64)
305         {
306             string rtnResult = string.Empty;
307             byte[] rtnValue = null;
308             byte[] keyArr = Encoding.UTF8.GetBytes(key);
309             byte[] ivArr = Encoding.UTF8.GetBytes(iv);
310             byte[] dataArr = Convert.FromBase64String(dataEnBase64);
311 
312             rtnValue = Des3DecodeCBC(keyArr, ivArr, dataArr);
313 
314             rtnResult = Encoding.UTF8.GetString(rtnValue).TrimEnd(\0);    // 去除多余空字符
315 
316             return rtnResult;
317         }
318 
319         /// <summary>
320         /// 3DES 解密(字符串参数和返回值)
321         /// </summary>
322         /// <param name="key">密钥</param>
323         /// <param name="iv">向量</param>
324         /// <param name="data">明文</param>
325         /// <returns></returns>
326         public static string Des3DecodeECB(string key, string iv, byte[] dataArr)
327         {
328             string rtnResult = string.Empty;
329             byte[] rtnValue = null;
330             byte[] keyArr = Encoding.UTF8.GetBytes(key);
331             byte[] ivArr = Encoding.UTF8.GetBytes(iv);
332 
333             rtnValue = Des3DecodeECB(keyArr, ivArr, dataArr);
334 
335             rtnResult = Encoding.UTF8.GetString(rtnValue).TrimEnd(\0);    // 去除多余空字符
336 
337             return rtnResult;
338         }
339 
340         #endregion
341 
342         #region 原加解密方法
343         
344 
345         /// <summary>
346         /// DES3 ECB模式加密
347         /// </summary>
348         /// <param name="key">密钥</param>
349         /// <param name="iv">IV(当模式为ECB时,IV无用)</param>
350         /// <param name="str">明文的byte数组</param>
351         /// <returns>密文的byte数组</returns>
352         public static byte[] Des3EncodeECB(byte[] key, byte[] iv, byte[] data)
353         {
354             try
355             {
356                 // Create a MemoryStream.
357                 MemoryStream mStream = new MemoryStream();
358 
359                 TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
360                 tdsp.Mode = CipherMode.ECB;
361                 tdsp.Padding = PaddingMode.PKCS7;
362                 // Create a CryptoStream using the MemoryStream 
363                 // and the passed key and initialization vector (IV).
364                 CryptoStream cStream = new CryptoStream(mStream,
365                     tdsp.CreateEncryptor(key, iv),
366                     CryptoStreamMode.Write);
367 
368                 // Write the byte array to the crypto stream and flush it.
369                 cStream.Write(data, 0, data.Length);
370                 cStream.FlushFinalBlock();
371 
372                 // Get an array of bytes from the 
373                 // MemoryStream that holds the 
374                 // encrypted data.
375                 byte[] ret = mStream.ToArray();
376 
377                 // Close the streams.
378                 cStream.Close();
379                 mStream.Close();
380 
381                 // Return the encrypted buffer.
382                 return ret;
383             }
384             catch (CryptographicException e)
385             {
386                 Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
387                 return null;
388             }
389 
390         }
391 
392         /// <summary>
393         /// DES3 ECB模式解密
394         /// </summary>
395         /// <param name="key">密钥</param>
396         /// <param name="iv">IV(当模式为ECB时,IV无用)</param>
397         /// <param name="str">密文的byte数组</param>
398         /// <returns>明文的byte数组</returns>
399         public static byte[] Des3DecodeECB(byte[] key, byte[] iv, byte[] data)
400         {
401             try
402             {
403                 // Create a new MemoryStream using the passed 
404                 // array of encrypted data.
405                 MemoryStream msDecrypt = new MemoryStream(data);
406 
407                 TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
408                 tdsp.Mode = CipherMode.ECB;
409                 tdsp.Padding = PaddingMode.PKCS7;
410 
411                 // Create a CryptoStream using the MemoryStream 
412                 // and the passed key and initialization vector (IV).
413                 CryptoStream csDecrypt = new CryptoStream(msDecrypt,
414                     tdsp.CreateDecryptor(key, iv),
415                     CryptoStreamMode.Read);
416 
417                 // Create buffer to hold the decrypted data.
418                 byte[] fromEncrypt = new byte[data.Length];
419 
420                 // Read the decrypted data out of the crypto stream
421                 // and place it into the temporary buffer.
422                 csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
423 
424                 //Convert the buffer into a string and return it.
425                 return fromEncrypt;
426             }
427             catch (CryptographicException e)
428             {
429                 Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
430                 return null;
431             }
432         }
433 
434         #endregion
435 
436         #endregion
437 
438         /// <summary>
439         /// 类测试
440         /// </summary>
441         public static void Test()
442         {
443             System.Text.Encoding utf8 = System.Text.Encoding.UTF8;
444 
445             // 扩展方法测试
446             string keyExt = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4";
447             string ivExt = "12345678";
448             string dataExt = "吴@#@\0\n";
449 
450             // CBC 模式
451             string tmpEnCBC = Des3Tool.Des3EncodeCBC(keyExt, ivExt, dataExt);       // 返回 base64
452             string tmpDeCBC = Des3Tool.Des3DecodeCBC(keyExt, ivExt, tmpEnCBC);       // 返回 utf8格式字符串
453 
454             System.Console.WriteLine(tmpEnCBC);
455             System.Console.WriteLine(tmpDeCBC);
456 
457             System.Console.WriteLine();
458 
459             // ECB 带 iv
460             string tmpEnECB = Des3Tool.Des3DecodeECB(keyExt, ivExt, dataExt);       // 返回 base64
461             string tmpDeECB = Des3Tool.Des3DecodeECB(keyExt, ivExt, tmpEnECB);       // 返回 utf8格式字符串
462 
463             System.Console.WriteLine(tmpEnECB);
464             System.Console.WriteLine(tmpDeECB);
465 
466             System.Console.WriteLine();
467 
468             // ECB 不带 iv
469             string tmpEnECBNoIv = Des3Tool.Des3DecodeECB(keyExt, dataExt);       // 返回 base64
470             string tmpDeECBNoIv = Des3Tool.Des3DecodeECB(keyExt, tmpEnECBNoIv);       // 返回 utf8格式字符串
471 
472             System.Console.WriteLine(tmpEnECBNoIv);
473             System.Console.WriteLine(tmpDeECBNoIv);
474 
475             System.Console.WriteLine();
476 
477 
478 
479             //key为abcdefghijklmnopqrstuvwx的Base64编码
480             byte[] key = Convert.FromBase64String("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4");
481             byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };      //当模式为ECB时,IV无用
482             byte[] data = utf8.GetBytes("中国ABCabc123");
483 
484             System.Console.WriteLine("ECB模式:");
485             byte[] str1 = Des3Tool.Des3EncodeECB(key, iv, data);
486             byte[] str2 = Des3Tool.Des3DecodeECB(key, iv, str1);
487             System.Console.WriteLine(Convert.ToBase64String(str1));
488             System.Console.WriteLine(System.Text.Encoding.UTF8.GetString(str2));
489 
490             System.Console.WriteLine();
491 
492             System.Console.WriteLine("CBC模式:");
493             byte[] str3 = Des3Tool.Des3EncodeCBC(key, iv, data);
494             byte[] str4 = Des3Tool.Des3DecodeCBC(key, iv, str3);
495             System.Console.WriteLine(Convert.ToBase64String(str3));
496             System.Console.WriteLine(utf8.GetString(str4));
497 
498             System.Console.WriteLine();
499 
500         }
501 
502     }
503 
504 }

 

Java 代码

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Des3 {
    public static void main(String[] args) throws Exception {

        byte[] key=new BASE64Decoder().decodeBuffer("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4");
        byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 };

        byte[] data="中国ABCabc123".getBytes("UTF-8");
        
        System.out.println("ECB加密解密");
        byte[] str3 = des3EncodeECB(key,data );
        byte[] str4 = ees3DecodeECB(key, str3);
        System.out.println(new BASE64Encoder().encode(str3));
        System.out.println(new String(str4, "UTF-8"));

        System.out.println();

        System.out.println("CBC加密解密");
        byte[] str5 = des3EncodeCBC(key, keyiv, data);
        byte[] str6 = des3DecodeCBC(key, keyiv, str5);
        System.out.println(new BASE64Encoder().encode(str5));
        System.out.println(new String(str6, "UTF-8"));

    }

    /**
     * ECB加密,不要IV
     * @param key 密钥
     * @param data 明文
     * @return Base64编码的密文
     * @throws Exception
     */
    public static byte[] des3EncodeECB(byte[] key, byte[] data)
            throws Exception {

        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);

        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");

        cipher.init(Cipher.ENCRYPT_MODE, deskey);
        byte[] bOut = cipher.doFinal(data);

        return bOut;
    }

    /**
     * ECB解密,不要IV
     * @param key 密钥
     * @param data Base64编码的密文
     * @return 明文
     * @throws Exception
     */
    public static byte[] ees3DecodeECB(byte[] key, byte[] data)
            throws Exception {

        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);

        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");

        cipher.init(Cipher.DECRYPT_MODE, deskey);

        byte[] bOut = cipher.doFinal(data);

        return bOut;

    }

    /**
     * CBC加密
     * @param key 密钥
     * @param keyiv IV
     * @param data 明文
     * @return Base64编码的密文
     * @throws Exception
     */
    public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data)
            throws Exception {

        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);

        Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
        IvParameterSpec ips = new IvParameterSpec(keyiv);
        cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
        byte[] bOut = cipher.doFinal(data);

        return bOut;
    }

    /**
     * CBC解密
     * @param key 密钥
     * @param keyiv IV
     * @param data Base64编码的密文
     * @return 明文
     * @throws Exception
     */
    public static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data)
            throws Exception {

        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);

        Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
        IvParameterSpec ips = new IvParameterSpec(keyiv);

        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);

        byte[] bOut = cipher.doFinal(data);

        return bOut;

    }

}

 

C# Java 3DES加密解密 扩展及修正\0 问题

标签:des   style   blog   http   io   ar   color   os   sp   

原文地址:http://www.cnblogs.com/wuyifu/p/4132005.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!