Delphi DES PKCS5Padding 配对 JAVA DES 加解密

Delphi DES PKCS5Padding 配对 JAVA DES 加解密,第1张

Delphi DES PKCS5Padding 配对 JAVA DES 加解密

Java代码:


密文 String originKey = "Rd058oh1";
明文:abcd
加密:QPnjW18Bbiw=
解密:abcd

Delphi部分

 

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,EncdDecd;

type
  TForm2 = class(TForm)
    Label1: TLabel;
    eStr: TEdit;
    eKey: TEdit;
    Label2: TLabel;
    eResult: TEdit;
    Label3: TLabel;
    Button3: TButton;
    Button1: TButton;
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

uses UDES_PKCS5Padding;

{$R *.dfm}


function StrTobase64(const Str: string): string;
var
  I, J, K, Len, Len1: Integer;
  B3: array[0..2] of Byte;
  B4: array[0..3] of Byte;
begin
  if Str = '' then
  begin
    Result := '';
    Exit;
  end;
  Len := Length(Str);
  Len1 := ((Len + 2) div 3) shl 2;
  SetString(Result, nil, Len1);
  I := 1;
  J := 1;
  while I <= Len do
  begin
    for K := 0 to 2 do
      if K + I > Len then B3[K] := 0
      else B3[K] := Ord(Str[K + I]);
    B4[0] := B3[0] shr 2;
    B4[1] := ((B3[0] shl 4) or (B3[1] shr 4)) and 63;
    B4[2] := ((B3[1] shl 2) or (B3[2] shr 6)) and 63;
    B4[3] := B3[2] and 63;
    for K := 0 to 3 do
    begin
      case B4[K] of
        0..25: Result[J] := Chr(B4[K] + 65);   // 'A'..'Z'
        26..51: Result[J] := Chr(B4[K] + 71);  // 'a'..'z'(B4[K]-26+97)
        62: Result[J] := '+';
        63: Result[J] := '/';
      else Result[J] := Chr(B4[K] - 4);        // '0'..'9'(B4[K]-52+48)
      end;
//      Result[J] := base64_Chars[B4[K] + 1];
      Inc(J);
    end;
    Inc(I, 3);
  end;
  K := 3 - Len mod 3 - 1;
  if K <> 2 then
    for I := Len1 - K to Len1 do
      Result[I] := '=';
end;

function base64ToStr(const base64: string): string;
var
  I, J, K, Len, Len1: Integer;
  B4: array[0..3] of Byte;
begin
  if base64 = '' then
  begin
    Result := '';
    Exit;
  end;
  Len := Length(base64);
  if Len and 3 <> 0 then
    raise Exception.Create('Invalid base64 length');
  Len1 := (Len shr 2) * 3;
  SetString(Result, nil, Len1);
  I := 1;
  J := 1;
  while I <= Len do
  begin
    for K := 0 to 3 do
    begin
      case base64[I] of
        'A'..'Z': B4[K] := Ord(base64[I]) - 65;
        'a'..'z': B4[K] := Ord(base64[I]) - 71;
        '0'..'9': B4[K] := Ord(base64[I]) + 4;
        '+': B4[K] := 62;
        '/': B4[K] := 63;
        '=': B4[K] := 0;
      else raise Exception.CreateFmt('#%d: Invalid char in base64', [Ord(base64[I])]);
      end;
      Inc(I);
    end;
    {Result[J] := Chr((B4[0] shl 2) or (B4[1] shr 4));
    Result[J + 1] := Chr((B4[1] shl 4) or (B4[2] shr 2));
    Result[J + 2] := Chr((B4[2] shl 6) or B4[3]); }
    Result[J] := Chr((B4[0] shl 2) or (B4[1] shr 4));
    Result[J + 1] := Chr(((B4[1] shl 4) or (B4[2] shr 2)) and 255);
    Result[J + 2] := Chr(((B4[2] shl 6) or B4[3]) and 255);
    Inc(J, 3);
  end;
  I := Pos('=', base64);
  if I <> 0 then
  begin
    I := Len - I + 1;
    Delete(Result, Len1 - I + 1, I);
  end;
end;

function HexToInt(hex: string): integer;
var
  i: integer;
  function Ncf(num, f: integer): integer;
  var
    i: integer;
  begin
    Result := 1;
    if f = 0 then exit;
    for i := 1 to f do
      result := result * num;
  end;
  function HexCharToInt(HexToken: char): integer;
  begin
    if HexToken > #97 then
      HexToken := Chr(Ord(HexToken) - 32);
      Result := 0;
    if (HexToken > #47) and (HexToken < #58) then { chars 0....9 }
      Result := Ord(HexToken) - 48
    else if (HexToken > #64) and (HexToken < #71) then { chars A....F }
      Result := Ord(HexToken) - 65 + 10;
  end;
begin
  result := 0;
    hex := ansiuppercase(trim(hex));
  if hex = '' then
    exit;
  for i := 1 to length(hex) do
  result := result + HexCharToInt(hex[i]) * ncf(16, length(hex) - i);
end;

function StringToHex(str: string): string;
var
 i : integer;
 s : string;
begin
 for i:=1 to length(str) do
 begin
   s := s + InttoHex(Integer(str[i]),2);
 end;
 Result:=s;
end;

function hextostring(str: string): string;
var
  s,t:string;
  i,j:integer;
  p:pchar;
begin
  s:='';
  i:=1;
  while i< length(str) do
  begin
    t:=str[i]+str[i+1];
    s:=s+chr(hextoint(t));
    i:=i+2;
  end;
  result:=s;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  aStr,aKey,aResult,sResult : String;
begin
  aResult := eResult.Text;
  aKey :=  eKey.Text;
  aResult := base64ToStr(aResult);
  aResult := StringToHex(aResult);
  aStr := DecryDes(aResult,aKey,'');
  eStr.Text := aStr;
end;

procedure TForm2.Button3Click(Sender: TObject);
var
  aStr,aKey,aResult,sResult : String;
begin
  aStr := eStr.Text;
  aKey := eKey.Text;
  aResult := EncryDes(aStr,aKey,'');
  aResult := hextostring(aResult);
  eResult.Text := StrTobase64(aResult);
end;

end.







unit UDES_PKCS5Padding;
{*********************************************************}
{* DELPHI、PHP、C#通用DES编码解码单元 *}
{* 由TurboPower LockBox部分代码改写 *}
{* 滕州市东鸣软件工作室制作 ZWF 2011-12-27 *}
{*********************************************************}
{EncryDes为编码函数,DecryDes为解码函数,keystr为密码,ivstr为偏移量,
一般设置keystr,ivstr相同,内容为八位字节长度的字符串,编码结果为十六进制字串}

interface

uses

Windows,SysUtils,Math;

type
  PKey64 = ^TKey64;
  TKey64 = array [0..7] of Byte;

type
  TDESBlock = array[0..7] of Byte;
  TDESContext = packed record
  TransformedKey : array [0..31] of LongInt;
  Encrypt : Boolean;

end;

  function EncryDes(str:string;const keystr:string;const ivstr:string):string ;
  function DecryDes(str:string;const keystr:string;const ivstr:string):string ;
  function DecryDessec(str:string;const keystr:string;const ivstr:string):string ;

implementation

procedure XorMemPrim(var Mem1; const Mem2; Count : Cardinal); register;
asm
  push esi
  push edi
  mov esi, eax //esi = Mem1
  mov edi, edx //edi = Mem2
  push ecx //save byte count
  shr ecx, 2 //convert to dwords
  jz @Continue
  cld
  @Loop1: //xor dwords at a time
  mov eax, [edi]
  xor [esi], eax
  add esi, 4
  add edi, 4
  dec ecx
  jnz @Loop1
  @Continue: //handle remaining bytes (3 or less)
  pop ecx
  and ecx, 3
  jz @Done
  @Loop2: //xor remaining bytes
  mov al, [edi]
  xor [esi], al
  inc esi
  inc edi
  dec ecx
  jnz @Loop2
  @Done:
  pop edi
  pop esi
end;

{ -------------------------------------------------------------------------- }
procedure XorMem(var Mem1; const Mem2; Count : Cardinal);
begin
  XorMemPrim(Mem1, Mem2, Count);
end;

{ -------------------------------------------------------------------------- }

procedure EncryptDES(const Context : TDESContext; var Block : TDESBlock);
const
  SPBox : array [0..7, 0..63] of DWord =
((010400, < 28) then
      begin
        PC1R[J] := PC1M[L];
        PC1R[J + 28] := PC1M[L + 28];
      end
      else
      begin
        PC1R[J] := PC1M[L - 28];
        PC1R[J + 28] := PC1M[L];
      end;
    end;
    {select bits individually}
    FillChar(KS, SizeOf(KS), 0);
    for J := 0 to 47 do
    if Boolean(PC1R[PC2[J]]) then
    begin
      L := J div 6;
      KS[L] := KS[L] or CBitMask[J mod 6] shr 2;
    end;
    {now convert to odd/even interleaved form for use in F}
    if Encrypt then
    begin
      Context.TransformedKey[I * 2] := (LongInt(KS[0]) shl 24) or (LongInt(KS[2]) shl 16) or
      (LongInt(KS[4]) shl 8) or (LongInt(KS[6]));
      Context.TransformedKey[I * 2 + 1] := (LongInt(KS[1]) shl 24) or (LongInt(KS[3]) shl 16) or
      (LongInt(KS[5]) shl 8) or (LongInt(KS[7]));
    end
    else
    begin
      Context.TransformedKey[31 - (I * 2 + 1)] := (LongInt(KS[0]) shl 24) or (LongInt(KS[2]) shl 16) or
      (LongInt(KS[4]) shl 8) or (LongInt(KS[6]));
      Context.TransformedKey[31 - (I * 2)] := (LongInt(KS[1]) shl 24) or (LongInt(KS[3]) shl 16) or
      (LongInt(KS[5]) shl 8) or (LongInt(KS[7]));
    end;
  end;
  Context.Encrypt := Encrypt;
end;

procedure EncryptDESCBC(const Context : TDESContext; const Prev : TDESBlock; var Block : TDESBlock);
begin
  if Context.Encrypt then
  begin
    XorMem(Block, Prev, SizeOf(Block));
    EncryptDES(Context, Block);
  end
  else
  begin
    EncryptDES(Context, Block);
    XorMem(Block, Prev, SizeOf(Block));
  end;
end;

function EncryDes(str:string;const keystr:string;const ivstr:string):string ;
var
  key:tkey64;
  Context:TDESContext;
  Block,iv:TDESBlock;
  i,j,len,posnum:smallint;
  poschar,xx:char;
  xuhuan:integer;
begin
  for i:=0 to 7 do
  begin
  if i >000000, <=8 then
    //xuhuan:=0
    xuhuan:=1
  else
    //xuhuan:=round(len/8);
    xuhuan := ceil(len/8);
  for i:=0 to xuhuan - 1 do
  begin
    for j:=0 to 7 do
    begin
    if ((i*8+j+1)<=len) then
    begin
      poschar := str[i*8+j+1];
      block[j] := byte(poschar);
    end
    else
      block[j] := byte(xx);
    end;
    EncryptDESCBC(Context, IV, Block);
    for j:= 0 to 7 do
    begin
      posnum := block[j];
      result := result + inttohex(posnum,2);
    end;
    //iv:=block;
  end;
end;

function DecryDessec(str:string;const keystr:string;const ivstr:string):string ;
var
  key:tkey64;
  Context:TDESContext;
  bak,Block,iv:TDESBlock;
  i,j,len,posnum:smallint;
  poschar,xx:char;
  res,lss,temp:string;
begin
  temp := keystr;
  res := '';
  for i:=0 to 7 do
  begin
  if i >010000, 010404, 010004, <=len) then
      begin
        poschar:=res[i*8+j+1];
        block[j]:=byte(poschar);
      end
      else
      begin
        block[j]:=byte(xx);
      end;
    end;
    bak:=block;
    EncryptDESCBC(Context, IV, Block);
    for j:= 0 to 7 do
    begin
      if block[j] >010404, 
000004,

010000,

000400, 010400, 010404, 000400, 000404, 010004, 000000, 000004, 000404, 000400, 000400, 010400, 010400, 010000, 010000, 000404, 010004, 000004, 000004, 010004, 000000, 000404, 010404, 000000, 010000, 010404, 000004, 010000, 010400, 000000, 000000, 000400, 010004, 010000, 010400, 000004, 000400, 000004, 000404, 010404, 010404, 010004, 010000, 000404, 000004, 000404, 010404, 010400, 000404, 000400, 000400, 000000, 010004, 010400, 000000, 010004), (108020, 008000, 008000, 108020, 100000, 000020, 100020, 008020, 000020, 108020, 108000, 000000, 008000, 100000, 000020, 100020, 108000, 100020, 008020, 000000, 000000, 008000, 108020, 100000, 100020, 000020, 000000, 108000, 008020, 108000, 100000, 008020, 000000, 108020, 100020, 100000, 008020, 100000, 108000, 008000, 100000, 008000, 000020, 108020, 108020, 000020, 008000, 000000, 008020, 108000, 100000, 000020, 100020, 008020, 000020, 100020, 108000, 000000, 008000, 008020, 000000, 100020, 108020, 108000), (000208, 020200, 000000, 020008, 000200, 000000, 020208, 000200, 020008, 000008, 000008, 020000, 020208, 020008, 020000, 000208, 000000, 000008, 020200, 000200, 020200, 020000, 020008, 020208, 000208, 020200, 020000, 000208, 000008, 020208, 000200, 000000, 020200, 000000, 020008, 000208, 020000, 020200, 000200, 000000, 000200, 020008, 020208, 000200, 000008, 000200, 000000, 020008, 000208, 020000, 000000, 020208, 000008, 020208, 020200, 000008, 020000, 000208, 000208, 020000, 020208, 000008, 020008, 020200), (802001, 002081, 002081, 000080, 802080, 800081, 800001, 002001, 000000, 802000, 802000, 802081, 000081, 000000, 800080, 800001, 000001, 002000, 800000, 802001, 000080, 800000, 002001, 002080, 800081, 000001, 002080, 800080, 002000, 802080, 802081, 000081, 800080, 800001, 802000, 802081, 000081, 000000, 000000, 802000, 002080, 800080, 800081, 000001, 802001, 002081, 002081, 000080, 802081, 000081, 000001, 002000, 800001, 002001, 802080, 800081, 002001, 002080, 800000, 802001, 000080, 800000, 002000, 802080), (000100, 080100, 080000, 000100, 080000, 000100, 000000, 080000, 080100, 080000, 000100, 080100, 000100, 080000, 080100, 000000, 000000, 080000, 080000, 000000, 000100, 080100, 080100, 000100, 080000, 000100, 000000, 000000, 080100, 000000, 000000, 080100, 080000, 000100, 000100, 000000, 000000, 080000, 000100, 080100, 000100, 000000, 080000, 080100, 080100, 000100, 000000, 080000, 080100, 080100, 000000, 080100, 080000, 000000, 080000, 000000, 080100, 000100, 000100, 080000, 000000, 080000, 080100, 000100), (000010, 400000, 004000, 404010, 400000, 000010, 404010, 400000, 004000, 404010, 400000, 000010, 400010, 004000, 000000, 004010, 000000, 400010, 004010, 004000, 404000, 004010, 000010, 400010, 400010, 000000, 404010, 404000, 004010, 404000, 404000, 000000, 004000, 000010, 400010, 404000, 404010, 400000, 004010, 000010, 400000, 004000, 000000, 004010, 000010, 404010, 404000, 400000, 404010, 404000, 000000, 400010, 000010, 004000, 400000, 404010, 004000, 400010, 004010, 000000, 404000, 000000, 400010, 004010), (200000, 200002, 000802, 000000, 000800, 000802, 200802, 200800, 200802, 200000, 000000, 000002, 000002, 000000, 200002, 000802, 000800, 200802, 200002, 000800, 000002, 200000, 200800, 200002, 200000, 000800, 000802, 200802, 200800, 000002, 000000, 200800, 000000, 200800, 200000, 000802, 000802, 200002, 200002, 000002, 200002, 000000, 000800, 200000, 200800, 000802, 200802, 200800, 000802, 000002, 200802, 200000, 200800, 000000, 000002, 200802, 000000, 200802, 200000, 000800, 000002, 000800, 000800, 200002), (001040, 001000, 040000, 041040, 000000, 001040, 000040, 000000, 040040, 040000, 041040, 041000, 041000, 041040, 001000, 000040, 040000, 000040, 001000, 001040, 041000, 040040, 040040, 041000, 001040, 000000, 000000, 040040, 000040, 001000, 041040, 040000, 041040, 040000, 041000, 001000, 000040, 040040, 001000, 041040, 001000, 000040, 000040, 040000, 040040, 000000, 040000, 001040, 000000, 041040, 040040, 000040, 040000, 001000, 001040, 000000, 041040, 041000, 041000, 001040, 001040, 040040, 000000, 041000)); var I, L, R, Work : DWord; CPtr : PDWord; procedure SplitBlock(const Block : TDESBlock; var L, R : DWord); register; asm push ebx push eax mov eax, [eax] mov bh, al mov bl, ah rol ebx, 16 shr eax, 16 mov bh, al mov bl, ah mov [edx], ebx pop eax mov eax, [eax+4] mov bh, al mov bl, ah rol ebx, 16 shr eax, 16 mov bh, al mov bl, ah mov [ecx], ebx pop ebx end; procedure JoinBlock(const L, R : LongInt; var Block : TDESBlock); register; asm push ebx mov bh, al mov bl, ah rol ebx, 16 shr eax, 16 mov bh, al mov bl, ah mov [ecx+4], ebx mov bh, dl mov bl, dh rol ebx, 16 shr edx, 16 mov bh, dl mov bl, dh mov [ecx], ebx pop ebx end; procedure IPerm(var L, R : DWord); var Work : DWord; begin Work := ((L shr 4) xor R) and F0F0F0F; R := R xor Work; L := L xor Work shl 4; Work := ((L shr 16) xor R) and 00FFFF; R := R xor Work; L := L xor Work shl 16; Work := ((R shr 2) xor L) and 333333; L := L xor Work; R := R xor Work shl 2; Work := ((R shr 8) xor L) and FF00FF; L := L xor Work; R := R xor Work shl 8; R := (R shl 1) or (R shr 31); Work := (L xor R) and $AAAAAAAA; L := L xor Work; R := R xor Work; L := (L shl 1) or (L shr 31); end; procedure FPerm(var L, R : DWord); var Work : DWord; begin L := L; R := (R shl 31) or (R shr 1); Work := (L xor R) and $AAAAAAAA; L := L xor Work; R := R xor Work; L := (L shr 1) or (L shl 31); Work := ((L shr 8) xor R) and FF00FF; R := R xor Work; L := L xor Work shl 8; Work := ((L shr 2) xor R) and 333333; R := R xor Work; L := L xor Work shl 2; Work := ((R shr 16) xor L) and 00FFFF; L := L xor Work; R := R xor Work shl 16; Work := ((R shr 4) xor L) and F0F0F0F; L := L xor Work; R := R xor Work shl 4; end; begin SplitBlock(Block, L, R); IPerm(L, R); CPtr := @Context; for I := 0 to 7 do begin Work := (((R shr 4) or (R shl 28)) xor CPtr^); Inc(CPtr); L := L xor SPBox[6, Work and F]; L := L xor SPBox[4, Work shr 8 and F]; L := L xor SPBox[2, Work shr 16 and F]; L := L xor SPBox[0, Work shr 24 and F]; Work := (R xor CPtr^); Inc(CPtr); L := L xor SPBox[7, Work and F]; L := L xor SPBox[5, Work shr 8 and F]; L := L xor SPBox[3, Work shr 16 and F]; L := L xor SPBox[1, Work shr 24 and F]; Work := (((L shr 4) or (L shl 28)) xor CPtr^); Inc(CPtr); R := R xor SPBox[6, Work and F]; R := R xor SPBox[4, Work shr 8 and F]; R := R xor SPBox[2, Work shr 16 and F]; R := R xor SPBox[0, Work shr 24 and F]; Work := (L xor CPtr^); Inc(CPtr); R := R xor SPBox[7, Work and F]; R := R xor SPBox[5, Work shr 8 and F]; R := R xor SPBox[3, Work shr 16 and F]; R := R xor SPBox[1, Work shr 24 and F]; end; FPerm(L, R); JoinBlock(L, R, Block); end; procedure InitEncryptDES(const Key : TKey64; var Context : TDESContext; Encrypt : Boolean); const PC1 : array [0..55] of Byte = (56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3); PC2 : array [0..47] of Byte = (13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31); CTotRot : array [0..15] of Byte = (1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28); CBitMask : array [0..7] of Byte = (128, 64, 32, 16, 8, 4, 2, 1); var PC1M : array [0..55] of Byte; PC1R : array [0..55] of Byte; KS : array [0..7] of Byte; I, J, L, M : LongInt; begin {convert PC1 to bits of key} for J := 0 to 55 do begin L := PC1[J]; M := L mod 8; PC1M[J] := Ord((Key[L div 8] and CBitMask[M]) <> 0); end; {key chunk for each iteration} for I := 0 to 15 do begin {rotate PC1 the right amount} for J := 0 to 27 do begin L := J + CTotRot[I]; if (L (length(keystr)-1) then key[i] :=0 else key[i] := byte(keystr[i+1]); end; for i:=0 to 7 do begin if i > (length(ivstr)-1) then iv[i]:=0 else iv[i] := byte(ivstr[i+1]); end; InitEncryptDES(Key, Context, true); len := length(AnsiString(str)); if len mod 8 = 0 then begin str := str + #8#8#8#8#8#8#8#8; len := len + 8; end; xx:= char( 8- (len mod 8)); if len (length(temp)-1) then key[i] :=0 else key[i] := byte(temp[i+1]); end; temp := ivstr; for i:=0 to 7 do begin if i > (length(temp)-1) then iv[i] := 0 else iv[i] := byte(temp[i+1]); end; InitEncryptDES(Key, Context, False); temp := str; posnum := 0; for i:=0 to length(temp)-1 do begin Block[posnum] := byte(temp[i+1]); posnum := posnum+1; if posnum = 8 then begin bak := block; EncryptDESCBC(Context, IV, Block); for j:= 0 to 7 do begin // temp := temp+inttostr(byte(block[i]))+' '; res := res + char(block[j]); end; iv := bak; posnum := 0; end; end; if posnum <> 0 then begin end else begin temp:=''; for i:= 1 to length(res) do begin temp := temp+char(res[i]); end; Result:= trim(temp); end; end; function DecryDes(str:string;const keystr:string;const ivstr:string):string ; var key:tkey64; Context:TDESContext; bak,Block,iv:TDESBlock; i,j,len,posnum:smallint; poschar,xx:char; res,lss:string; begin for i:=0 to 7 do begin if i > (length(keystr)-1) then key[i] :=0 else key[i] := byte(keystr[i+1]); end; for i:=0 to 15 do begin if i > (length(ivstr)-1) then iv[i]:=0 else iv[i] := byte(ivstr[i+1]); end; InitEncryptDES(Key, Context, false); res:=''; for j:= 0 to (length(str) div 2)-1 do begin lss:=copy(str,j*2+1,2); res:=res+ char(StrToInt('$'+lss)) ; end; //len := length(AnsiString(res)); len := length(res); for i:=0 to round(len/8)-1 do begin for j:=0 to 7 do begin if ((i*7+j+1) 32 then result := result + char(block[j]); end; //iv:=bak; end; end; end.

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

原文地址: http://outofmemory.cn/zaji/5707824.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存