用c完成DES加密过程中的1轮的迭代变换过程

用c完成DES加密过程中的1轮的迭代变换过程,第1张

DES算法处理的数据对象是一组64比特的明文串设该明文串为m=m1m2…m64 (mi=0或1)明文串经过64比特的密钥K来加密,最后生成长度为64比特的密文E其加密过程图示如下:

DES算法加密过程

对DES算法加密过程图示的说明如下:待加密的64比特明文串m,经过IP置换后,得到的比特串的下标列表如下:

IP 58 50 42 34 26 18 10 2

60 52 44 36 28 20 12 4

62 54 46 38 30 22 14 6

64 56 48 40 32 24 16 8

57 49 41 33 25 17 9 1

59 51 43 35 27 19 11 3

61 53 45 37 29 21 13 5

63 55 47 39 31 23 15 7

/ d3desh -

Headers and defines for d3desc

Graven Imagery, 1992

Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge

(GEnie : OUTER; CIS : [71755,204])

/

#define D2_DES / include double-length support /

#define D3_DES / include triple-length support /

#ifdef D3_DES

#ifndef D2_DES

#define D2_DES / D2_DES is needed for D3_DES /

#endif

#endif

#define EN0 0 / MODE == encrypt /

#define DE1 1 / MODE == decrypt /

/ A useful alias on 68000-ish machines, but NOT USED HERE /

typedef union {

unsigned long blok[2];

unsigned short word[4];

unsigned char byte[8];

} M68K;

extern void deskey(unsigned char , short);

/ hexkey[8] MODE

Sets the internal key register according to the hexadecimal

key contained in the 8 bytes of hexkey, according to the DES,

for encryption or decryption according to MODE

/

extern void usekey(unsigned long );

/ cookedkey[32]

Loads the internal key register with the data in cookedkey

/

extern void cpkey(unsigned long );

/ cookedkey[32]

Copies the contents of the internal key register into the storage

located at &cookedkey[0]

/

extern void des(unsigned char , unsigned char );

/ from[8] to[8]

Encrypts/Decrypts (according to the key currently loaded in the

internal key register) one block of eight bytes at address 'from'

into the block at address 'to' They can be the same

/

#ifdef D2_DES

#define desDkey(a,b) des2key((a),(b))

extern void des2key(unsigned char , short);

/ hexkey[16] MODE

Sets the internal key registerS according to the hexadecimal

keyS contained in the 16 bytes of hexkey, according to the DES,

for DOUBLE encryption or decryption according to MODE

NOTE: this clobbers all three key registers!

/

extern void Ddes(unsigned char , unsigned char );

/ from[8] to[8]

Encrypts/Decrypts (according to the keyS currently loaded in the

internal key registerS) one block of eight bytes at address 'from'

into the block at address 'to' They can be the same

/

extern void D2des(unsigned char , unsigned char );

/ from[16] to[16]

Encrypts/Decrypts (according to the keyS currently loaded in the

internal key registerS) one block of SIXTEEN bytes at address 'from'

into the block at address 'to' They can be the same

/

extern void makekey(char , unsigned char );

/ password, single-length key[8]

With a double-length default key, this routine hashes a NULL-terminated

string into an eight-byte random-looking key, suitable for use with the

deskey() routine

/

#define makeDkey(a,b) make2key((a),(b))

extern void make2key(char , unsigned char );

/ password, double-length key[16]

With a double-length default key, this routine hashes a NULL-terminated

string into a sixteen-byte random-looking key, suitable for use with the

des2key() routine

/

#ifndef D3_DES / D2_DES only /

#define useDkey(a) use2key((a))

#define cpDkey(a) cp2key((a))

extern void use2key(unsigned long );

/ cookedkey[64]

Loads the internal key registerS with the data in cookedkey

NOTE: this clobbers all three key registers!

/

extern void cp2key(unsigned long );

/ cookedkey[64]

Copies the contents of the internal key registerS into the storage

located at &cookedkey[0]

/

#else / D3_DES too /

#define useDkey(a) use3key((a))

#define cpDkey(a) cp3key((a))

extern void des3key(unsigned char , short);

/ hexkey[24] MODE

Sets the internal key registerS according to the hexadecimal

keyS contained in the 24 bytes of hexkey, according to the DES,

for DOUBLE encryption or decryption according to MODE

/

extern void use3key(unsigned long );

/ cookedkey[96]

Loads the 3 internal key registerS with the data in cookedkey

/

extern void cp3key(unsigned long );

/ cookedkey[96]

Copies the contents of the 3 internal key registerS into the storage

located at &cookedkey[0]

/

extern void make3key(char , unsigned char );

/ password, triple-length key[24]

With a triple-length default key, this routine hashes a NULL-terminated

string into a twenty-four-byte random-looking key, suitable for use with

the des3key() routine

/

#endif / D3_DES /

#endif / D2_DES /

desh文件

#ifndef CRYPTOPP_DES_H

#define CRYPTOPP_DES_H

#include "cryptlibh"

#include "misch"

NAMESPACE_BEGIN(CryptoPP)

class DES : public BlockTransformation

{

public:

DES(const byte userKey, CipherDir);

void ProcessBlock(const byte inBlock, byte  outBlock) const;

void ProcessBlock(byte  inoutBlock) const

{DES::ProcessBlock(inoutBlock, inoutBlock);}

enum {KEYLENGTH=8, BLOCKSIZE=8};

unsigned int BlockSize() const {return BLOCKSIZE;}

protected:

static const word32 Spbox[8][64];

SecBlock<word32> k;

};

class DESEncryption : public DES

{

public:

DESEncryption(const byte  userKey)

: DES (userKey, ENCRYPTION) {}

};

class DESDecryption : public DES

{

public:

DESDecryption(const byte  userKey)

: DES (userKey, DECRYPTION) {}

};

class DES_EDE_Encryption : public BlockTransformation

{

public:

DES_EDE_Encryption(const byte  userKey)

: e(userKey, ENCRYPTION), d(userKey + DES::KEYLENGTH, DECRYPTION) {}

void ProcessBlock(const byte inBlock, byte  outBlock) const;

void ProcessBlock(byte  inoutBlock) const;

enum {KEYLENGTH=16, BLOCKSIZE=8};

unsigned int BlockSize() const {return BLOCKSIZE;}

private:

DES e, d;

};

class DES_EDE_Decryption : public BlockTransformation

{

public:

DES_EDE_Decryption(const byte  userKey)

: d(userKey, DECRYPTION), e(userKey + DES::KEYLENGTH, ENCRYPTION) {}

void ProcessBlock(const byte inBlock, byte  outBlock) const;

void ProcessBlock(byte  inoutBlock) const;

enum {KEYLENGTH=16, BLOCKSIZE=8};

unsigned int BlockSize() const {return BLOCKSIZE;}

private:

DES d, e;

};

class TripleDES_Encryption : public BlockTransformation

{

public:

TripleDES_Encryption(const byte  userKey)

: e1(userKey, ENCRYPTION), d(userKey + DES::KEYLENGTH, DECRYPTION),

e2(userKey + 2DES::KEYLENGTH, ENCRYPTION) {}

void ProcessBlock(const byte inBlock, byte  outBlock) const;

void ProcessBlock(byte  inoutBlock) const;

enum {KEYLENGTH=24, BLOCKSIZE=8};

unsigned int BlockSize() const {return BLOCKSIZE;}

private:

DES e1, d, e2;

};

class TripleDES_Decryption : public BlockTransformation

{

public:

TripleDES_Decryption(const byte  userKey)

: d1(userKey + 2DES::KEYLENGTH, DECRYPTION), e(userKey + DES::KEYLENGTH, ENCRYPTION),

d2(userKey, DECRYPTION) {}

void ProcessBlock(const byte inBlock, byte  outBlock) const;

void ProcessBlock(byte  inoutBlock) const;

enum {KEYLENGTH=24, BLOCKSIZE=8};

unsigned int BlockSize() const {return BLOCKSIZE;}

private:

DES d1, e, d2;

};

NAMESPACE_END

#endif

descpp文件:

// descpp - modified by Wei Dai from:

/

 This is a major rewrite of my old public domain DES code written

 circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977

 public domain code I pretty much kept my key scheduling code, but

 the actual encrypt/decrypt routines are taken from from Richard

 Outerbridge's DES code as printed in Schneier's "Applied Cryptography"

 This code is in the public domain I would appreciate bug reports and

 enhancements

 Phil Karn KA9Q, karn@unixka9qamprorg, August 1994

/

#include "pchh"

#include "misch"

#include "desh"

NAMESPACE_BEGIN(CryptoPP)

/ Tables defined in the Data Encryption Standard documents

 Three of these tables, the initial permutation, the final

 permutation and the expansion operator, are regular enough that

 for speed, we hard-code them They're here for reference only

 Also, the S and P boxes are used by a separate program, genspc,

 to build the combined SP box, Spbox[] They're also here just

 for reference

/

#ifdef notdef

/ initial permutation IP /

static byte ip[] = {

58, 50, 42, 34, 26, 18, 10, 2,

60, 52, 44, 36, 28, 20, 12, 4,

62, 54, 46, 38, 30, 22, 14, 6,

64, 56, 48, 40, 32, 24, 16, 8,

57, 49, 41, 33, 25, 17, 9, 1,

59, 51, 43, 35, 27, 19, 11, 3,

61, 53, 45, 37, 29, 21, 13, 5,

63, 55, 47, 39, 31, 23, 15, 7

};

/ final permutation IP^-1 /

static byte fp[] = {

40, 8, 48, 16, 56, 24, 64, 32,

39, 7, 47, 15, 55, 23, 63, 31,

38, 6, 46, 14, 54, 22, 62, 30,

37, 5, 45, 13, 53, 21, 61, 29,

36, 4, 44, 12, 52, 20, 60, 28,

35, 3, 43, 11, 51, 19, 59, 27,

34, 2, 42, 10, 50, 18, 58, 26,

33, 1, 41, 9, 49, 17, 57, 25

};

/ expansion operation matrix /

static byte ei[] = {

32, 1, 2, 3, 4, 5,

4, 5, 6, 7, 8, 9,

8, 9, 10, 11, 12, 13,

12, 13, 14, 15, 16, 17,

16, 17, 18, 19, 20, 21,

20, 21, 22, 23, 24, 25,

24, 25, 26, 27, 28, 29,

28, 29, 30, 31, 32, 1

};

/ The (in)famous S-boxes /

static byte sbox[8][64] = {

/ S1 /

14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,

0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,

4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,

15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,

/ S2 /

15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,

3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,

0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,

13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,

/ S3 /

10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,

13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,

13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,

1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,

/ S4 /

7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,

13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,

10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,

3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,

/ S5 /

2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,

14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,

4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,

11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,

/ S6 /

12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,

10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,

9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,

4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,

/ S7 /

4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,

13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,

1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,

6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,

/ S8 /

13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,

1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,

7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,

2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11

};

/ 32-bit permutation function P used on the output of the S-boxes /

static byte p32i[] = {

16, 7, 20, 21,

29, 12, 28, 17,

1, 15, 23, 26,

5, 18, 31, 10,

2, 8, 24, 14,

32, 27, 3, 9,

19, 13, 30, 6,

22, 11, 4, 25

};

#endif

/ permuted choice table (key) /

static const byte pc1[] = {

57, 49, 41, 33, 25, 17, 9,

1, 58, 50, 42, 34, 26, 18,

10, 2, 59, 51, 43, 35, 27,

19, 11, 3, 60, 52, 44, 36,

63, 55, 47, 39, 31, 23, 15,

7, 62, 54, 46, 38, 30, 22,

14, 6, 61, 53, 45, 37, 29,

21, 13, 5, 28, 20, 12, 4

};

/ number left rotations of pc1 /

static const byte totrot[] = {

1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28

};

/ permuted choice key (table) /

static const byte pc2[] = {

14, 17, 11, 24, 1, 5,

3, 28, 15, 6, 21, 10,

23, 19, 12, 4, 26, 8,

16, 7, 27, 20, 13, 2,

41, 52, 31, 37, 47, 55,

30, 40, 51, 45, 33, 48,

44, 49, 39, 56, 34, 53,

46, 42, 50, 36, 29, 32

};

/ End of DES-defined tables /

/ bit 0 is left-most in byte /

static const int bytebit[] = {

0200,0100,040,020,010,04,02,01

};

/ Set key (initialize key schedule array) /

DES::DES(const byte key, CipherDir dir)

: k(32)

{

SecByteBlock buffer(56+56+8);

byte const pc1m=buffer; / place to modify pc1 into /

byte const pcr=pc1m+56; / place to rotate pc1 into /

byte const ks=pcr+56;

register int i,j,l;

int m;

for (j=0; j<56; j++) { / convert pc1 to bits of key /

l=pc1[j]-1; / integer bit location /

m = l & 07; / find bit /

pc1m[j]=(key[l>>3] & / find which key byte l is in /

bytebit[m]) / and which bit of that byte /

 1 : 0; / and store 1-bit result /

}

for (i=0; i<16; i++) { / key chunk for each iteration /

memset(ks,0,8); / Clear key schedule /

for (j=0; j<56; j++) / rotate pc1 the right amount /

pcr[j] = pc1m[(l=j+totrot[i])<(j<28 28 : 56)  l: l-28];

/ rotate left and right halves independently /

for (j=0; j<48; j++){ / select bits individually /

/ check bit that goes to ks[j] /

if (pcr[pc2[j]-1]){

/ mask it in if it's there /

l= j % 6;

ks[j/6] |= bytebit[l] >> 2;

}

}

/ Now convert to odd/even interleaved form for use in F /

k[2i] = ((word32)ks[0] << 24)

| ((word32)ks[2] << 16)

| ((word32)ks[4] << 8)

| ((word32)ks[6]);

k[2i+1] = ((word32)ks[1] << 24)

| ((word32)ks[3] << 16)

| ((word32)ks[5] << 8)

| ((word32)ks[7]);

}

if (dir==DECRYPTION) // reverse key schedule order

for (i=0; i<16; i+=2)

{

std::swap(k[i], k[32-2-i]);

std::swap(k[i+1], k[32-1-i]);

}

}

/ End of C code common to both versions /

/ C code only in portable version /

// Richard Outerbridge's initial permutation algorithm

/

inline void IPERM(word32 &left, word32 &right)

{

word32 work;

work = ((left >> 4) ^ right) & 0x0f0f0f0f;

right ^= work;

left ^= work << 4;

work = ((left >> 16) ^ right) & 0xffff;

right ^= work;

left ^= work << 16;

work = ((right >> 2) ^ left) & 0x33333333;

left ^= work;

right ^= (work << 2);

work = ((right >> 8) ^ left) & 0xff00ff;

left ^= work;

right ^= (work << 8);

right = rotl(right, 1);

work = (left ^ right) & 0xaaaaaaaa;

left ^= work;

right ^= work;

left = rotl(left, 1);

}

inline void FPERM(word32 &left, word32 &right)

{

word32 work;

right = rotr(right, 1);

work = (left ^ right) & 0xaaaaaaaa;

left ^= work;

right ^= work;

left = rotr(left, 1);

work = ((left >> 8) ^ right) & 0xff00ff;

right ^= work;

left ^= work << 8;

work = ((left >> 2) ^ right) & 0x33333333;

right ^= work;

left ^= work << 2;

work = ((right >> 16) ^ left) & 0xffff;

left ^= work;

right ^= work << 16;

work = ((right >> 4) ^ left) & 0x0f0f0f0f;

left ^= work;

right ^= work << 4;

}

/

// Wei Dai's modification to Richard Outerbridge's initial permutation

// algorithm, this one is faster if you have access to rotate instructions

// (like in MSVC)

inline void IPERM(word32 &left, word32 &right)

{

word32 work;

right = rotl(right, 4U);

work = (left ^ right) & 0xf0f0f0f0;

left ^= work;

right = rotr(right^work, 20U);

work = (left ^ right) & 0xffff0000;

left ^= work;

right = rotr(right^work, 18U);

work = (left ^ right) & 0x33333333;

left ^= work;

right = rotr(right^work, 6U);

work = (left ^ right) & 0x00ff00ff;

left ^= work;

right = rotl(right^work, 9U);

work = (left ^ right) & 0xaaaaaaaa;

left = rotl(left^work, 1U);

right ^= work;

}

inline void FPERM(word32 &left, word32 &right)

{

word32 work;

right = rotr(right, 1U);

work = (left ^ right) & 0xaaaaaaaa;

right ^= work;

left = rotr(left^work, 9U);

work = (left ^ right) & 0x00ff00ff;

right ^= work;

left = rotl(left^work, 6U);

work = (left ^ right) & 0x33333333;

right ^= work;

left = rotl(left^work, 18U);

work = (left ^ right) & 0xffff0000;

right ^= work;

left = rotl(left^work, 20U);

work = (left ^ right) & 0xf0f0f0f0;

right ^= work;

left = rotr(left^work, 4U);

}

// Encrypt or decrypt a block of data in ECB mode

void DES::ProcessBlock(const byte inBlock, byte  outBlock) const

{

word32 l,r,work;

#ifdef IS_LITTLE_ENDIAN

l = byteReverse((word32 )inBlock);

r = byteReverse((word32 )(inBlock+4));

#else

l = (word32 )inBlock;

r = (word32 )(inBlock+4);

#endif

IPERM(l,r);

const word32 kptr=k;

for (unsigned i=0; i<8; i++)

{

work = rotr(r, 4U) ^ kptr[4i+0];

l ^= Spbox[6][(work) & 0x3f]

^ Spbox[4][(work >> 8) & 0x3f]

^ Spbox[2][(work >> 16) & 0x3f]

^ Spbox[0][(work >> 24) & 0x3f];

work = r ^ kptr[4i+1];

l ^= Spbox[7][(work) & 0x3f]

^ Spbox[5][(work >> 8) & 0x3f]

^ Spbox[3][(work >> 16) & 0x3f]

^ Spbox[1][(work >> 24) & 0x3f];

work = rotr(l, 4U) ^ kptr[4i+2];

r ^= Spbox[6][(work) & 0x3f]

^ Spbox[4][(work >> 8) & 0x3f]

^ Spbox[2][(work >> 16) & 0x3f]

^ Spbox[0][(work >> 24) & 0x3f];

work = l ^ kptr[4i+3];

r ^= Spbox[7][(work) & 0x3f]

^ Spbox[5][(work >> 8) & 0x3f]

^ Spbox[3][(work >> 16) & 0x3f]

^ Spbox[1][(work >> 24) & 0x3f];

}

FPERM(l,r);

#ifdef IS_LITTLE_ENDIAN

(word32 )outBlock = byteReverse(r);

(word32 )(outBlock+4) = byteReverse(l);

#else

(word32 )outBlock = r;

(word32 )(outBlock+4) = l;

#endif

}

void DES_EDE_Encryption::ProcessBlock(byte inoutBlock) const

{

eProcessBlock(inoutBlock);

dProcessBlock(inoutBlock);

eProcessBlock(inoutBlock);

}

void DES_EDE_Encryption::ProcessBlock(const byte inBlock, byte outBlock) const

{

eProcessBlock(inBlock, outBlock);

dProcessBlock(outBlock);

eProcessBlock(outBlock);

}

void DES_EDE_Decryption::ProcessBlock(byte inoutBlock) const

{

dProcessBlock(inoutBlock);

eProcessBlock(inoutBlock);

dProcessBlock(inoutBlock);

}

void DES_EDE_Decryption::ProcessBlock(const byte inBlock, byte outBlock) const

{

dProcessBlock(inBlock, outBlock);

eProcessBlock(outBlock);

dProcessBlock(outBlock);

}

void TripleDES_Encryption::ProcessBlock(byte inoutBlock) const

{

e1ProcessBlock(inoutBlock);

dProcessBlock(inoutBlock);

e2ProcessBlock(inoutBlock);

}

void TripleDES_Encryption::ProcessBlock(const byte inBlock, byte outBlock) const

{

e1ProcessBlock(inBlock, outBlock);

dProcessBlock(outBlock);

e2ProcessBlock(outBlock);

}

void TripleDES_Decryption::ProcessBlock(byte inoutBlock) const

{

d1ProcessBlock(inoutBlock);

eProcessBlock(inoutBlock);

d2ProcessBlock(inoutBlock);

}

void TripleDES_Decryption::ProcessBlock(const byte inBlock, byte outBlock) const

{

d1ProcessBlock(inBlock, outBlock);

eProcessBlock(outBlock);

d2ProcessBlock(outBlock);

}

NAMESPACE_END

程序运行如下:

Solaris下的系统,有一个用C做的加密工具,调用Sunwcry的des(1)对文件进行加密,然后在java中对文件进行解密。java中用的是标准的DES/CBC/NoPadding算法,可是解密后发现开头有8byte的数据出错了,请高人指点一下。

cbc_encryptc : 加密用的C程序

cbc_decryptc:解密用的C程序

TestDescbcjava:解密用的java程序

Test01dat原始文件

Test03dat cbc_encrypt加密后的文件

Test05dat cbc_decrypt解密后的文件

Test06dat TestDescbc解密后的文件

以上就是关于用c完成DES加密过程中的1轮的迭代变换过程全部的内容,包括:用c完成DES加密过程中的1轮的迭代变换过程、用c实现des算法!!!、des加密算法(c/c++)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/10180548.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-06
下一篇 2023-05-06

发表评论

登录后才能评论

评论列表(0条)

保存