问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

哪位大哥能给我一个基于IDEA算法的c或者c++的软件以及源代码啊

发布网友 发布时间:2022-03-31 10:03

我来回答

1个回答

热心网友 时间:2022-03-31 11:32

c++ code
////////////////////////////////////////////////////////
//
// Project: Implementation of IDEA (International
// Data Encryption Algorithm)
//
// ECE 575 Term Project
// Winter 2003
// Author: Irwin Yoon
//
// Overview: This code does the following:
// - print out all encryption and
// decryption subkeys which are used
// in the encryption and decryption
// process
// - encrypts plaintext message
// - decrypts ciphertext message
// - shows detailed, round by round results
// (8 total)
// Program contains a user driven menu where the user can select
// initial 128-bit key and also select messages to decrypt
// and encrypt.
//
// Compiling: This has been verified to work on SunOS
// with g++ compiler (flop.engr.orst.e).
// To Compile: g++ Idea.cpp -o Idea.exe
//
// Note: This code is a little sloppy. Coding could
// be made more efficient.
//
// Usage: Run executable with no arguments: Idea.exe
// Then select appropriate menu options
//
//
//
//////////////////////////////////////////////

// main() is at the bottom of file!

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <cassert>
#include <string>

//globals
#define NUMSUBKEYS 52
#define NUMROUNDS 8
#define MAXINPUTSIZE 32

// I had problems if we use #define with
// these nums. Problem arose when taking
// mod of this number
unsigned int TWOPOWER16 = 65536;
unsigned int TWOPOWER161 = 65537;
unsigned int inputsize;

// all the subkey information
unsigned short esubkeys[NUMSUBKEYS];
unsigned short dsubkeys[NUMSUBKEYS];
unsigned int origkeyint[4];
unsigned char origkeychar[17];

//****************************************
// argument is an array of chars and prints
// the hex value of 4 consecutive chars (4 bytes)
// starting at the pointer. It loops until
// all the bits in the original string are read
//****************************************

void printHex (unsigned char* start)
{
unsigned int* val = (unsigned int*)start;
int times = inputsize/4;
cout <<endl;
for (int i=0; i<times;i++) {
printf ("\t\tbits %03d to %03d: 0x%08x\n",(32*i)+1,8*4*(i+1),*val);
start+=4;
val = (unsigned int*)start;
}
}

//****************************************
// This is the core encryption and decryption
// engine which does all the rounds and does
// all the arithmetic operations (add,mult,xor,swap,inverse)
//****************************************

void runIdea(unsigned char* msg, unsigned char* outmsg,unsigned short* keysbit16,int writeflag)
{

//if writeflag is 1, then we print round by round results

unsigned short x1,x2,x3,x4;
unsigned short y1,y2,y3,y4;
unsigned short x5,x6,x7,x8,x9,x10;
unsigned short x11,x12,x13,x14;
unsigned short xtemp;
unsigned int writeint;

// msg is 1 byte. make 2 byte ptr to facilitate copying for
// 16 bit fields
// 2 bytes go into x1, 2 bytes go into x2,etc
unsigned short* msgbit16 = (unsigned short*) msg;
//cout << "msg is " << *msg <<endl;
x1 = *msgbit16++;
x2 = *msgbit16++;
x3 = *msgbit16++;
x4 = *msgbit16++;

//x1 = (x1 >>8) | (x1<<8);
//x2 = (x2 >>8) | (x2<<8);
//x3 = (x3 >>8) | (x3<<8);
//x4 = (x4 >>8) | (x4<<8);

// this is for debug purposes. make greater than 8
// if don't want debugs
int tst=9;

// note that mod 2^16+1 could yield a value which is 2^16.
// this is greater than space for 16 bits, so i think
// the mod operation makes 2^16 mod 2^16+1 equal to 0.

for (int i=0; i<NUMROUNDS;i++)
{
//IY

if (i==tst )
cout << "STEP 1: x1 is " << x1 << ", key is " << *keysbit16 << endl;
//STEP 1 of 14
x1 = (x1* (*keysbit16++)) % TWOPOWER161;
//IY
if (i==tst )
cout << "\tAfter mul, x1 is " << x1 << endl;

//IY
if (i==tst )
cout << "STEP 2: x2 is " << x2 << ", key is " << *keysbit16 << endl;

//STEP 2 of 14
x2 = (x2 + *keysbit16++) % TWOPOWER16;

//IY
if (i==tst )
cout << "\tAfter add, x2 is " << x2 << endl;

//IY
if (i==tst )
cout << "STEP 3: x3 is " << x3 << ", key is " << *keysbit16 << endl;
//STEP 3 of 14
x3 = (x3 + *keysbit16++) % TWOPOWER16;

//IY
if (i==tst )
cout << "\tAfter add, x3 is " << x3 << endl;

//IY
if (i==tst )
cout << "STEP 4: x4 is " << x4 << ", key is " << *keysbit16 << endl;

//STEP 4 of 14
x4 = (x4* (*keysbit16++)) % TWOPOWER161;
//IY
if (i==tst )
cout << "\tAfter mul, x4 is " << x4 << endl;

//IY
if (i==tst)
cout << "STEP 5: x3 is " << x3 << ", x1 is " << x1 << endl;

//STEP 5 of 14
x5 = x1^x3;
if (i==tst)
cout << "\tAfter XOR, x5 is " << x5 << endl;

//IY
if (i==tst)
cout << "STEP 6(outorder): x2 is " << x2 << ", x4 is " << x4 << endl;

//STEP 6 of 14
x6 = x2^x4;

//IY
if (i==tst)
cout << "\tAfter XOR, x6 is " << x6 << endl;

//IY
if (i==tst)
cout << "STEP 7(outorder): x5 is " << x5 << ", key is " << *keysbit16 << endl;

//STEP 7 of 14
x7 = (x5* (*keysbit16++)) % TWOPOWER161;

if (i==tst)
cout << "\tAfter mul, x7 is " << x7 << endl;

//IY
if (i==tst)
cout << "STEP 8: x6 is " << x6 << ", x7 is " << x7 << endl;

//STEP 8 of 14
x8 = (x6+x7) % TWOPOWER16;

//IY
if (i==tst)
cout << "\tAfter ADD, x8 is " << x8 << endl;

//IY
if (i==tst)
cout << "STEP 9: x8 is " << x8 << ", key is " << *keysbit16 << endl;

//STEP 9 of 14
x9 = (x8* (*keysbit16++)) % TWOPOWER161;

//IY
if (i==tst)
cout << "\tAfter mul, x9 is " << x9 << endl;

//IY
if (i==tst)
cout << "STEP 10: x7 is " << x7 << ", x9 is " << x9 << endl;

//STEP 10 of 14
x10 = (x7+x9) % TWOPOWER16;
//IY
if (i==tst)
cout << "\tAfter add, x10 is " << x10 << endl;

//STEP 11,12,13,14 of 14
x11=x1^x9;
x12=x3^x9;
x13=x2^x10;
x14=x4^x10;

if (i==tst ) {
cout << "\tSTEP11: After XOR, x11 is " << x11 << endl;
cout << "\tSTEP12: After XOR, x12(after swap) is " << x12 << endl;
cout << "\tStep13: After XOR, x13(after swap) is " << x13 << endl;
cout << "\tStep14: After XOR, x14 is " << x14 << endl;
}

//new values for next iteration
x1=x11;
x2=x12;
x3=x13;
x4=x14;

if (writeflag==1) {
printf ("ROUND %d:\n", i+1);
writeint = (x1<<16) + x2;
printf("\tBits 1 to 32 0x%08x\n",writeint);
writeint = (x3<<16) + x4;
printf("\tBits 33 to 64 0x%08x\n\n",writeint);
}
} // foreach round

//final output transformation. modify 4 subkeys like so:
y1 = (x11 * (*keysbit16++)) % TWOPOWER161;
//flip flop these two!
y3 = (x13 + *keysbit16++) % TWOPOWER16;
y2 = (x12 + *keysbit16++) %TWOPOWER16;
y4 = (x14 * (*keysbit16)) % TWOPOWER161;

// put new data into the buffer
msgbit16=(unsigned short*)outmsg;

*msgbit16++ = y1;
*msgbit16++ = y3;
*msgbit16++ = y2;
*msgbit16 = y4;

//*msgbit16++ = (y1 >>8) | (y1<<8);
//*msgbit16++ = (y3 >>8) | (y3<<8);
//*msgbit16++ = (y2 >>8) | (y2<<8);
//*msgbit16 = (y4 >>8) | (y4<<8);

if (writeflag==1) {
unsigned int tempint;
printf ("AFTER OUTPUT TRANSFORMATION AND SWAP:\n");
msgbit16=(unsigned short*)outmsg;
tempint = (y1 <<16) + y3;
printf ("\tBits 1 to 32 0x%08x\n",tempint);
tempint = (y2 <<16) + y4;
printf ("\tBits 33 to 64 0x%08x\n",tempint);
}
} // end runIdea

//****************************************
// each block is 8 bytes (64 bits), so
// we loop until all blocks have been encrypted
// essentially hands over work to runIdea
//****************************************

void encrypt (unsigned char* msg,unsigned char* outmsg,int writeflag)
{
int blocks = inputsize/8;
unsigned char* inptr=msg;
unsigned char* outptr=outmsg;
for(int i=0;i<blocks;i++) {
if (writeflag==1) {
printf ("Results for Data Block %d\n", i+1);
printf ("=======================\n\n");
}
runIdea(inptr,outptr,esubkeys,writeflag);
inptr+=8;
outptr+=8;
}
}

//****************************************
// each block is 8 bytes (64 bits), so
// we loop until all blocks have been decrypted
// essentially hands over work to runIdea
//****************************************
void decrypt (unsigned char* msg,unsigned char* outmsg,int writeflag)
{
int blocks = inputsize/8;
unsigned char* inptr=msg;
unsigned char* outptr=outmsg;
for(int i=0;i<blocks;i++) {
if (writeflag==1) {
printf ("Results for Data Block %d\n", i+1);
printf ("=======================\n\n");
}
runIdea(inptr,outptr,dsubkeys,writeflag);
inptr+=8;
outptr+=8;
}
} //end of decrypt

//****************************************
// Finds the inverse of a 16 bit number mod 2^16+1
// uses extended euclidean algorithm
//****************************************

//unsigned short inv(unsigned short b)
short inv(unsigned short b)
{

// what book said to do if taking mod of 0 or 1
if (b==0 || b==1)
return b;

// initial variables
int a = 65536+1; // 2^16 + 1
int g0 = a;
int g1 = b;
int v0 = 0;
int v1 = 1;
int savev0;
int q;
int rem;
int numloops = 0;

// start of extended euglidean algorithm
while (g1 != 0) {
numloops++;
q = g0/g1;
rem = g0 % g1;
g0=g1;
g1 = rem;
savev0=v0;
v0 = v1;
v1 = savev0 - (v1*q);
}
assert (g0==1);

//IMPORTANT - since we're dealing wih signs, if we end up with a negative
// number, for some reason the positive equivalent was off by 1. so add
// 1 to value if negative result was found. Not sure why.
if (v0 >1)
return v0;
else
return 1+v0;
} // end inv

//****************************************
// Prints the original 128 bit key in hex
//****************************************
void printOrigKey()
{
printf ("Original Key in text: %s\n",origkeychar);
printf ("\tOriginal Key 1st 32bits: 0x%08x\n",origkeyint[0]);
printf ("\tOriginal Key 2nd 32bits: 0x%08x\n",origkeyint[1]);
printf ("\tOriginal Key 3rd 32bits: 0x%08x\n",origkeyint[2]);
printf ("\tOriginal Key 4th 32bits: 0x%08x\n",origkeyint[3]);
}

//****************************************
// Prints out the 52 subkeys used for encryption
// and decryption
//****************************************
void printKeys()
{

int count=1;
cout << "\n\n***** ENCRYPTION AND DECRYPTION SUBKEY SUMMARY *****" <<endl;
cout << endl << "All Subkeys are 16 bits." <<endl<<endl;

printOrigKey();

for (int k=0; k<NUMSUBKEYS;k++) {
if (k%6 ==0) {
cout <<"\nEncryption Subkeys Round " << count ;
cout <<" Decryption Subkeys Round " << count << endl;
count++;
}
printf (" subkey %02d 0x%08x",k,esubkeys[k]);
printf (" subkey %02d 0x%08x\n",k,dsubkeys[k]);

}

}//end printKeys

//****************************************
// based on the 52 encryption subkeys, find
// tje 52 decryption subkeys (16 bit)
//****************************************
void calcDKeys ()
{

//*** 1st,4th subkey for each round
for (int i=0;i<NUMSUBKEYS;i+=6) {
dsubkeys[i] = inv(esubkeys[48-i]);
dsubkeys[i+3] = inv(esubkeys[48-i+3]);
}

//*** 2nd, 3rd subkey for each round
dsubkeys[1] = -1 * esubkeys[49]; //first round
dsubkeys[2] = -1 * esubkeys[50]; //first round

for (int i =7; i<NUMSUBKEYS;i+=6) {
dsubkeys[i] = -1 * esubkeys[51-i];
dsubkeys[i+1] = -1 * esubkeys[50-i];
}
dsubkeys[49] = -1 * esubkeys[1]; //last round
dsubkeys[50] = -1 * esubkeys[2]; //last round

//*** 5th, 6th subkey for each round
for (int i=4; i< (NUMSUBKEYS) ; i+=6) {
dsubkeys[i] = esubkeys[50-i];
dsubkeys[i+1] = esubkeys[51-i];
}

int count=1;
for (int k=0; k<NUMSUBKEYS;k++) {
if (k%6 ==0) {
//IY cout <<"\nDSUBKEYS FOR ROUND " << count << endl;
count++;
}
//IY cout <<"subkey " << k << " = " << dsubkeys[k]<<endl;
}
} //end calcDKeys

//****************************************
// Takes original 128 bit key which is
// passed in as array of bytes and
// calculate encryption subkeys (52 total - 16 bits)
//****************************************
void calcEKeys(unsigned char* userkey)
{

//keys from example
//char userkey[16];

//for(int i=0; i<16; i++)
//userkey[i] = i+1;

int firstbyte = 0;

//merge two 8-bit sections into one 16 bit!!!
// this is done by bitwise shifting. most of logic in this
// funciton is because of this

for (int j=0; j<8;j++) {
esubkeys[j] = (userkey[firstbyte] <<8) + userkey[firstbyte+1];
firstbyte = firstbyte+2;
}

for (int f=8; f<NUMSUBKEYS-4;f+=8) {
//shift 25 bits.
//if we're on subkey 1, then get last 7 bits of subkey 2, and
//first 9 bits of subkey 2

// first 6 subkeys
for (int n=0;n<6;n++) {
esubkeys[f+n] = (short) ((esubkeys[f+n-7] <<9) | (esubkeys[f+n-6] >>7));
}

// next 2 esubkeys
esubkeys[f+6] = (short) ((esubkeys[f+6-7] <<9) | (esubkeys[f+6-6-8]>>7));
esubkeys[f+7] = (short) ((esubkeys[f+7-7-8] <<9) | (esubkeys[f+7-6-8]>>7));
}

// subkeys 48-51
esubkeys[NUMSUBKEYS-4] = (short) ((esubkeys[NUMSUBKEYS-4-7] <<9) | (esubkeys[NUMSUBKEYS-4-6] >>7));
esubkeys[NUMSUBKEYS-4+1] = (short) ((esubkeys[NUMSUBKEYS-4+1-7] <<9) | (esubkeys[NUMSUBKEYS-4+1-6] >>7));
esubkeys[NUMSUBKEYS-4+2] = (short) ((esubkeys[NUMSUBKEYS-4+2-7] <<9) | (esubkeys[NUMSUBKEYS-4+2-6] >>7));
esubkeys[NUMSUBKEYS-4+3] = (short) ((esubkeys[NUMSUBKEYS-4+3-7] <<9) | (esubkeys[NUMSUBKEYS-4+3-6] >>7));

int count=1;
for (int k=0; k<NUMSUBKEYS;k++) {
if (k%6 ==0) {
//cout <<"\nSUBKEYS FOR ROUND " << count << endl;
count++;
}
//cout <<"subkey " << k<< " = " << esubkeys[k]<<endl;
}
} //end calcEKeys

//****************************************
// states that program has started.
//****************************************
void promptWelcome()
{
if (sizeof(unsigned short)!=2){
cout <<" size of unsigned short is not 2 bytes. Please run on flop.engr.orst.e or on another machine. This program needs 2 bytes for unsigned short to simulate the 16-bit subkeys" <<endl;
exit(0);
}

cout << endl <<endl;
cout << "************ WELCOME ***************" <<endl;
cout << "This is Irwin Yoon's program illustrating " <<endl;
cout << "IDEA (International Data Encryption Algorithm)" <<endl;
cout << "************************************" <<endl;
cout << endl <<endl;
} //end promptWelcome

//****************************************
// prompt the user to enter either plaintext
// or ciphertext. puts value in array
// that is passed in
//****************************************
void promptForText(unsigned char* ptext,int encryptionflag)
{

std::string str;
if (encryptionflag ==1)
cout << endl << "************ ENCRYPTION OF PLAINTEXT **********" <<endl<<endl;
else
cout << endl << "************ DECRYPTION OF CIPHERTEXT **********" <<endl<<endl;
while (1) {
cout << "Data block size is 8 bits. " <<endl;
cout << "Therefore, please enter 8, 16, 24, 32 characters" <<endl;
if (encryptionflag ==1)
cout << "Your Plaintext input: ";
else
cout << "Your Ciphertext input: ";

getline(cin, str);

if ((str.size() == 8) || (str.size()==16) || (str.size()==24) || (str.size()==32))
break;
else
cout <<endl<< "ERROR: input was " << str.size()<< " instead of 8,16,24,32 chars. Try Again" <<endl <<endl;
}
inputsize = str.size();

for (int i=0;i<str.size();i++) {
ptext[i] = str[i];
}
ptext[inputsize]='\0';
} //prompt for plaintext

//****************************************
// We have to prompt user to enter 128 bit
// key. since we only have 1 byte chars
// make the user enter 16 characters, which
// we convert to 128 bit key
//****************************************
void promptForKey()
{
cout << "IDEA takes in a 128-bit key. " <<endl;
cout << "User will enter 16 alphanumeric characters" <<endl;
cout << "These 16 alphanumeric characters will be "<< endl;
cout << "converted to a 128-bit key. " <<endl;
cout << " (16 char * 8bits = 128 bits)" <<endl;

cout << endl <<endl;

std::string str;
while (1) {
cout << "Please enter 16 alphanumberic characters, then press enter" <<endl;
getline(cin, str);

if (str.size() == 16)
break;
else
cout <<endl<< "ERROR: That was not 16 alphanumeric chars. Try Again" <<endl <<endl;
}

for (int i=0;i<16;i++) {
origkeychar[i] = str[i];

}
origkeychar[16]='\0';
cout << endl << "Thank you."<<endl ;

//translate to hex
int firstbyte = 0;
for (int j=0; j<4;j++) {
//merge two 8-bit sections into one 16 bit
origkeyint[j] = (origkeychar[firstbyte] <<24) + (origkeychar[firstbyte+1]<<16)
+ (origkeychar[firstbyte+2]<<8) + (origkeychar[firstbyte+3]);
firstbyte = firstbyte+4;
}
printOrigKey();
} //end promptForKey

//****************************************
// prints hex and ascii of plaintext
//****************************************
void printPlainTextSummary(unsigned char* plaintext)
{
plaintext[inputsize]='\0';
printf ("\n\nYour Plaintext\n");
printf ("=================================\n");
printf ("Plaintext in ASCII: \"%s\"\n",plaintext);
printf ("Plaintext in Hex:");
printHex(plaintext);
}

//****************************************
// prints hex of ciphertext
//****************************************
void printCipherTextSummary(unsigned char* ciphertext)
{
ciphertext[inputsize] = '\0';
printf ("\n\nThe Resulting Ciphertext\n");
printf ("=================================\n");
printf ("Ciphertext in Hex:");
printHex(ciphertext);
}

//****************************************
// prints hex and ascii of decrypted
// ciphertext
//****************************************
void printDecipherTextSummary(unsigned char* decipheredtext)
{
decipheredtext[inputsize] = '\0';
printf ("\n\nDecrypt the Ciphertext\n");
printf ("=================================\n");
printf ("Decrypted text in ASCII: \"%s\"\n",decipheredtext);
printf ("Decrypted text in Hex:");
printHex(decipheredtext);
}

//****************************************
// THE MAIN LOOP! CONTINUALLY prompts
// user for input and processes request
//****************************************

int main()
{

promptWelcome();
promptForKey();

//NOTE: override user prompted key only for testing purposes
//unsigned char origkeychar[17];
//for(int i=0; i<16; i++)
//origkeychar[i] = i+1;
//origkeychar[16]='\0';

calcEKeys(origkeychar);
calcDKeys();

std::string str;
unsigned char ciphertext[MAXINPUTSIZE+1];
unsigned char decipheredtext[MAXINPUTSIZE+1];
unsigned char plaintext[MAXINPUTSIZE+1];
ciphertext[MAXINPUTSIZE] = '\0';
decipheredtext[MAXINPUTSIZE] = '\0';
unsigned int myint;
unsigned int* intptr;

//*********************
//******** MAIN LOOP
//*********************

while (1) {
cout << endl <<endl << "MAIN MENU" <<endl;
cout << "=========" <<endl;
cout << "Press 1 to print all Encryption/decryption keys " <<endl;
cout << "Press 2 to encrypt plaintext with intermediate results" <<endl;
cout << "Press 3 to decipher ciphertext with intermediate results" <<endl;
cout << "Press 4 to encrypt, then decrypt "
<< "(No intermediate results shown)" <<endl;
cout << "Press 5 to quit " <<endl<<endl;
cout << "Your choice: " ;
getline(cin, str);

// I should probably use switch statements instead, but it's
// too late
if (str[0] == '1')
printKeys();
else if (str[0]=='2') {
promptForText(plaintext,1);
encrypt(plaintext,ciphertext,1);
printCipherTextSummary(ciphertext);
}
else if (str[0]=='3') {
promptForText(ciphertext,0);
decrypt(ciphertext,decipheredtext,1);
printDecipherTextSummary(decipheredtext);
}
else if(str[0]=='4') {
promptForText(plaintext,1);
encrypt(plaintext,ciphertext,0);
decrypt(ciphertext,decipheredtext,0);
printPlainTextSummary(plaintext);
printCipherTextSummary(ciphertext);
printDecipherTextSummary(decipheredtext);

}
else if(str[0]=='5') {
cout << "****** Exiting IDEA program. Good bye. " <<endl<<endl;
exit(0);
}
else {
cout <<"Error: Invalid input" <<endl;
}

} // end main loop

return 0;
} //end main
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
国外留学有用吗 花钱出国留学有用吗 !这叫什么号 百万医疗赔付后是否可以续保 前一年理赔过医疗险还能续保吗? 医疗住院险理赔后还能购买吗? 女生多大后可以不在长身高? 如何不用软件把手机投屏到电脑上手机屏幕怎样投放到电脑上 战时拒绝、故意延误军事订货罪既遂的处罚? 战时故意延误军事订货罪处罚标准 拳击比赛的比赛级别是怎样划分的 拳击比赛公斤级别什么意思? 拳击比赛等级划分 拳击怎么分级别? 拳击中中量级是指多少公斤级 拳击多少公斤级是怎么定的? 拳击比赛中的中量级是指多少公斤? 拳击中的公斤级是指的什么?又是如何划分的? 拳击比赛中的级别如何划分 拳手体重怎么划分为轻量/中量/重量级呢?… 超中量级的发展历程 拳击分为多少公斤级? 拳击量级如何划分? 拳击级别怎么划分? 超中量级的介绍 效率的功率如何表示,公式是什么? 功率的计算公式 求初中物理力学公式(越详细越好) 初中拉力计算公式 如何制作一张好的学术海报(poster)? 学术类海报必须有的三部分是什么? 高质量学术报告海报是怎样的? a3学术海报怎么做 你看见过高质量的学术海报是怎样的? 海报是什么 制作海报要有什么要素 要相关文章吗 如何制作青年学术论坛的海报(大型彩喷) 会议论文海报怎么做?优秀的论文海报应该具备怎样的特质 商业海报设计有哪些种类? 用什么苹果软件制作学术海报 如何把PPT做的学术海报输出成300dpi的jpg格式 IDEA加密算法适合iOSAPP开发吗 给珍珠起名字,比如倾月珠 姓于男孩,叫珍,中间加个什么字好 珍珠DIY取个主题名字 寓意为珍珠的女孩英文名是什么? 跪求能人帮我的珍珠饰品起个浪漫的名字!! 梦见猫,蛇,兔,相互撕咬 珍珠项链起名字 帮忙给我家的珍珠产品取个名字