Create TOC

2000년 11월 16일

Linux 시스템 이전하기

이 문서는 구형 시스템에서 새 시스템으로 사용하던 Linux환경을 그대로 이전하는 방법을 설명한다.

새 시스템 준비

  1. 구형 시스템에 새 시스템에 붙일 하드 디스크를 연결한다.
  2. 파티션을 나누고 mkfs 를 이용해서 파일 시스템을 준비한다.

데이타 백업

  1. 새 파티션을 mount 한다. /mnt/new 로 mount 했다고 가정한다.
  2. rsync 명령을 사용해서 기존 파티션의 내용을 복사한다. rsync --recursive --times --perms --owner --group --links --hard-links --one-file-system -stats 원본 경로 /mnt/new 원본 경로는 /dev를 제외한 나머지를 하나 씩 넣어준다. 이런 식으로 /dev를 제외한 파티션을 복사한다.
  3. /dev는 아래와 같이 복사한다. rsync --recursive --times --perms --owner --group --links --hard-links --one-file-system -stats /dev/.static/dev /mnt/new/dev/.static/dev
  4. /mnt/new/etc/lilo.conf를 새 시스템에 맞게 편집한다.

lilo 준비

  1. 새 하드디스크를 새로운 시스템에 설치한 다음 debian 설치 CD로 부팅해서 파티션 나누는 화면까지 진행한다.
  2. 관리 콘솔로 들어가서 새 부팅 파티션을 mount 한다. 이 문서에서는 /mnt/new 에 mount 했다고 가정한다.
  3. chroot /mnt/new 로 root를 변경한다.
  4. mknod 명령으로 필요한 hdxx 장치를 만들어준다.
  5. /sbin/lilo 명령으로 lilo를 재설치한다.
  6. dpkg-reconfigure linux-image-xxxxx 명령으로 부팅 용 ramdisk를 만든다.
  7. mknod로 만들었던 장치를 제거한다.
  8. 시스템을 새 하드로 부팅한다.

변경된 하드웨어 설정

  1. 사운드는 ''alsaconf''를 이용해서 다시 잡는다.
  2. X-windows는 새 시스템에 맞게 수정한다.
  3. lan의 경우 새 lan 카드가 eth1 로 잡히는 경우가 있다. 이때는 /etc/udev/rules.d/z25_persistent-net.rules 파일을 편집해서 옛 시스템의 lan 카드 정보를 지우고 새 lan 카드를 eth0가 되도록 수정한다.

2000년 5월 26일

gdb

조건

gdb로 디버깅하기 위해서는 gcc에 -g 옵션을 주고 컴파일해야 한다.

실행

gdb <실행파일명>

종료

quit

변수값 확인

print 변수명

Break/Watchpoints

breakpoint 설정

간단 설정

break <줄번호|함수명>

조건부 설정

break <줄번호> if <조건>

이미 설정된 breakpoint에 조건을 설정하려면 아래와 같이 하면 된다.

condition <break 번호> <조건>

breakpoint 목록 보기

info break

watchpoint 설정

watch <변수명|조건>

한줄씩 실행

한줄씩 실행. 함수 호출시 함수 내부로 들어가지 않는다.

next or n

한줄씩 실행. 함수 호출시 함수 내부로 들어간다.

step or s

계속 실행

continue

Stack trace

stack 출력

bt

출력 형식은 아래와 같다.

#frame번호 주소 in 함수명(인자) at 파일명:줄번호

예)

(gdb) bt
#0  0x80483ea in sum (a=8, b=8) at main.c:7
#1  0x8048435 in main (argc=1, argv=0xbffff9c4) at main.c:21

frame 이동

frame <frame번호>
up or down

지역변수 확인

info locals

예) backtrace 에서 특정 stack의 지역변수를 확인할때?

(gdb) frame 1
(gdb) info locals

Attach Process

gdb <실행파일명> <pid>

Palm/POSE와 gdb를 이용한 디버깅

prc-tools를 사용하면 m68k-palm-gdb를 사용해서 디버깅을 해야 한다.

디버깅을 위한 빌드

-g 옵션을 이용해 빌드한다.

# m68k-palmos-gcc -g -c hello.c -o hello.o
# m68k-palmos-gcc -g hello.o -o hello

이렇게 빌드하면 hello.prchello가 생성된다.

POSE 실행

POSE를 실행한다.

gdb 실행 및 설정

아래와 같이 m68k-palm-gdb를 실행한다.

# m68k-palmos-gdb hello
GNU gdb 5.3
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Thpe "show copyping" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
this GDB was configured as "--host=i686-pc-cygwin --target=m68k-palmos"...
(gdb)

gdb prompt 에서 아래와 같이 입력한다.

(gdb) target pilot localhost:6414
Remote debugging under PalmOS using localhost:6414
Waiting... (Press Ctrl-C to connect to halted machine)

디버깅

위 단계를 모두 거쳤으면 POSE에 hello.prc 를 설치하고 실행한다. hello.prc를 실행하는 순간 gdb에 아래와 같은 화면이 나온다.

Program received signal SIGSTOP, Stopped (signal).
0x00045888 in PilotMain (cmd=3, cmdPBP=0xa2260000, launchFlags=68) at hello.c:20
20 {
(gdb)

이제 디버깅을 하면 된다.

2000년 5월 15일

C++/Virtual Destructor

아래와 code를 보자.

class Sample {
public:
 Sample() { cout << "Sample" << endl; }
 ~Sample() { cout << "~Sample" << endl; }

};

class Derived : public Sample {
public:
 Derived() { cout << "Derived" << endl; }
 ~Derived() { cout << "~Derived" << endl; }
};


int main(int argc, char **argv)
{
 Sample *p = new Derived;

 delete p;
 return 0;
}

수행결과는 어떨까? 아마도

Sample
Derived
~Derived
~Sample

가 되어야 할 것처럼 보인다. 하지만 실제 수행해보면

Sample
Derived
~Sample

Derived의 destructor가 호출되지 않는 것을 볼 수 있다. 그 이유는 포인터 p는 Sample class 형 포인터 이기 때문에 Derived의 destructor을 알지 못한다. 따라서 위에 delete p 할 때 Sample의 destructor만을 호출하게 된다.

이 문제를 해결하기 위해서는 Simple class 에서 destructor 선언시 virtual 을 사용해야 한다.

virtual ~Sample() { cout << "~Sample" << endl; }

2000년 3월 8일

GCC

따로 찾기 귀찮아서 웹사이트에서 긁은 정보(주로 GCC 3.2 매뉴얼)를 모았습니다.

Standard Predefined Macros

__FILE__

This macro expands to the name of the current input file, in the form of a C string constant. This is the path by which the preprocessor opened the file, not the short name specified in #include or as the input file name argument. For example, "/usr/local/include/myheader.h" is a possible expansion of this macro.
__LINE__
This macro expands to the current input line number, in the form of a decimal integer constant. While we call it a predefined macro, it's a pretty strange macro, since its "definition" changes with each new line of source code.
__DATE__
This macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and looks like "Feb 12 1996". If the day of the month is less than 10, it is padded with a space on the left.
__TIME__
This macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks like "23:59:01".
__STDC__
In normal operation, this macro expands to the constant 1, to signify that this compiler conforms to ISO Standard C. If GNU CPP is used with a compiler other than GCC, this is not necessarily true; however, the preprocessor always conforms to the standard, unless the -traditional option is used. This macro is not defined if the -traditional option is used. On some hosts, the system compiler uses a different convention, where __STDC__ is normally 0, but is 1 if the user specifies strict conformance to the C Standard. GNU CPP follows the host convention when processing system header files, but when processing user files __STDC__ is always 1. This has been reported to cause problems; for instance, some versions of Solaris provide X Windows headers that expect __STDC__ to be either undefined or 1. You may be able to work around this sort of problem by using an -I option to cancel treatment of those headers as system headers. See Invocation.
__STDC_VERSION__
This macro expands to the C Standard's version number, a long integer constant of the form yyyymmL where yyyy and mm are the year and month of the Standard version. This signifies which version of the C Standard the compiler conforms to. Like __STDC__, this is not necessarily accurate for the entire implementation, unless GNU CPP is being used with GCC. The value 199409L signifies the 1989 C standard as amended in 1994, which is the current default; the value 199901L signifies the 1999 revision of the C standard. Support for the 1999 revision is not yet complete. This macro is not defined if the -traditional option is used, nor when compiling C++ or Objective-C.
__STDC_HOSTED__
This macro is defined, with value 1, if the compiler's target is a hosted environment. A hosted environment has the complete facilities of the standard C library available.
__cplusplus
This macro is defined when the C++ compiler is in use. You can use __cplusplus to test whether a header is compiled by a C compiler or a C++ compiler. This macro is similar to __STDC_VERSION__, in that it expands to a version number. A fully conforming implementation of the 1998 C++ standard will define this macro to 199711L. The GNU C++ compiler is not yet fully conforming, so it uses 1 instead. We hope to complete our implementation in the near future.

Common Predefined Macros

The common predefined macros are GNU C extensions. They are available with the same meanings regardless of the machine or operating system on which you are using GNU C. Their names all start with double underscores.

__GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__

These macros are defined by all GNU compilers that use the C preprocessor: C, C++, and Objective-C. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. They are defined only when the entire compiler is in use; if you invoke the preprocessor directly, they are not defined. __GNUC_PATCHLEVEL__ is new to GCC 3.0; it is also present in the widely-used development snapshots leading up to 3.0 (which identify themselves as GCC 2.96 or 2.97, depending on which snapshot you have). If all you need to know is whether or not your program is being compiled by GCC, you can simply test GNUC. If you need to write code which depends on a specific version, you must be more careful. Each time the minor version is increased, the patch level is reset to zero; each time the major version is increased (which happens rarely), the minor version and patch level are reset. If you wish to use the predefined macros directly in the conditional, you will need to write it like this:
/* Test for GCC > 3.2.0 */
#if __GNUC__ > 3 || \
    (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
                       (__GNUC_MINOR__ == 2 && \
                        __GNUC_PATCHLEVEL__ > 0))
Another approach is to use the predefined macros to calculate a single number, then compare that against a threshold:
#define GCC_VERSION (__GNUC__ * 10000 \
                     + __GNUC_MINOR__ * 100 \
                     + __GNUC_PATCHLEVEL__)
...
/* Test for GCC > 3.2.0 */
#if GCC_VERSION > 30200
Many people find this form easier to understand.
__OBJC__
This macro is defined, with value 1, when the Objective-C compiler is in use. You can use __OBJC__ to test whether a header is compiled by a C compiler or a Objective-C compiler.
__GNUC__
The GNU C++ compiler defines this. Testing it is equivalent to testing (__GNUC__ && __cplusplus).
__STRICT_ANSI__
GCC defines this macro if and only if the -ansi switch, or a -std switch specifying strict conformance to some version of ISO C, was specified when GCC was invoked. It is defined to 1. This macro exists primarily to direct GNU libc's header files to restrict their definitions to the minimal set found in the 1989 C standard.
__BASE_FILE__
This macro expands to the name of the main input file, in the form of a C string constant. This is the source file that was specified on the command line of the preprocessor or C compiler.
__INCLUDE_LEVEL__
This macro expands to a decimal integer constant that represents the depth of nesting in include files. The value of this macro is incremented on every #include directive and decremented at the end of every included file. It starts out at 0, it's value within the base file specified on the command line.
__VERSION__
This macro expands to a string constant which describes the version of the compiler in use. You should not rely on its contents having any particular form, but it can be counted on to contain at least the release number.
__OPTIMIZE__ __OPTIMIZE_SIZE__ __NO_INLINE__
These macros describe the compilation mode. __OPTIMIZE__ is defined in all optimizing compilations. __OPTIMIZE_SIZE__ is defined if the compiler is optimizing for size, not speed. __NO_INLINE__ is defined if no functions will be inlined into their callers (when not optimizing, or when inlining has been specifically disabled by -fno-inline). These macros cause certain GNU header files to provide optimized definitions, using macros or inline functions, of system library functions. You should not use these macros in any way unless you make sure that programs will execute with the same effect whether or not they are defined. If they are defined, their value is 1.
__CHAR_UNSIGNED__
GCC defines this macro if and only if the data type char is unsigned on the target machine. It exists to cause the standard header file limits.h to work correctly. You should not use this macro yourself; instead, refer to the standard macros defined in limits.h.
__REGISTER_PREFIX__
This macro expands to a single token (not a string constant) which is the prefix applied to CPU register names in assembly language for this target. You can use it to write assembly that is usable in multiple environments. For example, in the m68k-aout environment it expands to nothing, but in the m68k-coff environment it expands to a single %.
__USER_LABEL_PREFIX__
This macro expands to a single token which is the prefix applied to user labels (symbols visible to C code) in assembly. For example, in the m68k-aout environment it expands to an _, but in the m68k-coff environment it expands to nothing. This macro will have the correct definition even if -f(no-)underscores is in use, but it will not be correct if target-specific options that adjust this prefix are used (e.g. the OSF/rose -mno-underscores option).
__SIZE_TYPE__ __PTRDIFF_TYPE__ __WCHAR_TYPE__ __WINT_TYPE__
These macros are defined to the correct underlying types for the size_t, ptrdiff_t, wchar_t, and wint_t typedefs, respectively. They exist to make the standard header files stddef.h and wchar.h work correctly. You should not use these macros directly; instead, include the appropriate headers and use the typedefs.
__USING_SJLJ_EXCEPTIONS__
This macro is defined, with value 1, if the compiler uses the old mechanism based on setjmp and longjmp for exception handling.

Function Names as Strings

GCC predefines two magic identifiers to hold the name of the current function. The identifier __FUNCTION__ holds the name of the function as it appears in the source. The identifier __PRETTY_FUNCTION__ holds the name of the function pretty printed in a language specific fashion.

These names are always the same in a C function, but in a C++ function they may be different. For example, this program:

extern "C" {
extern int printf (char *, ...);
}

class a {
 public:
  sub (int i)
    {
      printf ("__FUNCTION__ = %s\n", __FUNCTION__);
      printf ("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__);
    }
};

int
main (void)
{
  a ax;
  ax.sub (0);
  return 0;
}

gives this output:

__FUNCTION__ = sub
__PRETTY_FUNCTION__ = int  a::sub (int)

The compiler automagically replaces the identifiers with a string literal containing the appropriate name. Thus, they are neither preprocessor macros, like __FILE__ and __LINE__, nor variables. This means that they catenate with other string literals, and that they can be used to initialize char arrays. For example char here = "Function " __FUNCTION__ " in " __FILE__; On the other hand, #ifdef __FUNCTION__ does not have any special meaning inside a function, since the preprocessor does not do anything special with the identifier __FUNCTION__.

Note that these semantics are deprecated, and that GCC 3.2 will handle __FUNCTION__ and __PRETTY_FUNCTION__ the same way as __func__. __func__ is defined by the ISO standard C99:

The identifier __func__ is implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration

static const char __func__[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing function. This name is the unadorned name of the function. By this definition, __func__ is a variable, not a string literal. In particular, __func__ does not catenate with other string literals.

In C++, __FUNCTION__ and __PRETTY_FUNCTION__ are variables, declared in the same way as __func__.

Macros with a Variable Number of Arguments.

In the ISO C standard of 1999, a macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is similar to that of a function. Here is an example:

#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

Here ... is a variable argument. In the invocation of such a macro, it represents the zero or more tokens until the closing parenthesis that ends the invocation, including any commas. This set of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears. See the CPP manual for more information.

GCC has long supported variadic macros, and used a different syntax that allowed you to give a name to the variable arguments just like any other argument. Here is an example:

#define debug(format, args...) fprintf (stderr, format, args)

This is in all ways equivalent to the ISO C example above, but arguably more readable and descriptive.

GNU CPP has two further variadic macro extensions, and permits them to be used with either of the above forms of macro definition.

In standard C, you are not allowed to leave the variable argument out entirely; but you are allowed to pass an empty argument. For example, this invocation is invalid in ISO C, because there is no comma after the string:

debug ("A message")

GNU CPP permits you to completely omit the variable arguments in this way. In the above examples, the compiler would complain, though since the expansion of the macro still has the extra comma after the format string.

To help solve this problem, CPP behaves specially for variable arguments used with the token paste operator, ##. If instead you write

#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

and if the variable arguments are omitted or empty, the ## operator causes the preprocessor to remove the comma before it. If you do provide some variable arguments in your macro invocation, GNU CPP does not complain about the paste operation and instead places the variable arguments after the comma. Just like any other pasted macro argument, these arguments are not macro expanded.

System별 predefine

Generated with gcc -E -dM:

Vaxstation

#define __vax__ 1
#define __vax 1
#define __unix 1
#define __unix__ 1
#define vax 1
#define __GNUC__ 2
#define unix 1

Linux (i386)

#define __linux__ 1
#define linux 1
#define __i386__ 1
#define __i386 1
#define i386 1
#define __unix 1
#define __unix__ 1
#define __GNUC__ 2
#define __linux 1
#define unix 1

NetBSD (i386)

#define __i386__ 1
#define __NetBSD__ 1
#define __i386 1
#define i386 1
#define __unix 1
#define __unix__ 1
#define __GNUC__ 2
#define unix 1

NetBSD (sparc)

#define __GCC_NEW_VARARGS__ 1
#define __NetBSD__ 1
#define __sparc 1
#define sparc 1
#define __unix 1
#define __unix__ 1
#define __GNUC__ 2
#define __sparc__ 1
#define unix 1

Decstation

#define __LANGUAGE_C 1
#define R3000 1
#define __SYSTYPE_BSD__ 1
#define SYSTYPE_BSD 1
#define __host_mips 1
#define ultrix 1
#define __MIPSEL__ 1
#define __ANSI_COMPAT 1
#define __MIPSEL 1
#define ___SYSTYPE_BSD 1
#define __mips__ 1
#define __mips 1
#define __host_mips__ 1
#define MIPSEL 1
#define __R3000__ 1
#define __ultrix__ 1
#define host_mips 1
#define __SYSTYPE_BSD 1
#define ___SYSTYPE_BSD__ 1
#define mips 1
#define __LANGUAGE_C__ 1
#define __unix 1
#define __R3000 1
#define __unix__ 1
#define __bsd4_2 1
#define __bsd4_2__ 1
#define __GNUC__ 2
#define __ultrix 1
#define LANGUAGE_C 1
#define _SYSTYPE_BSD 1
#define bsd4_2 1
#define unix 1

RS-6000

#define ___AIX 1
#define ___IBMR2__ 1
#define _AIX 1
#define ___AIX32 1
#define __CHAR_UNSIGNED__ 1
#define ___IBMR2 1
#define ___AIX__ 1
#define ___AIX32__ 1
#define _AIX32 1
#define __GNUC__ 2
#define _IBMR2 1

Sun (Solaris)

#define __GCC_NEW_VARARGS__ 1
#define __sparc 1
#define __svr4__ 1
#define __sun 1
#define sparc 1
#define __sun__ 1
#define __unix 1
#define __unix__ 1
#define sun 1
#define __GNUC__ 2
#define __sparc__ 1
#define unix 1

Sun (SunOS)

#define __GCC_NEW_VARARGS__ 1
#define __sparc 1
#define __GNUC_MINOR__ 5
#define __sun 1
#define sparc 1
#define __sun__ 1
#define __unix 1
#define __unix__ 1
#define sun 1
#define __GNUC__ 2
#define __sparc__ 1
#define unix 1

SGI

#define sgi 1
#define __EXTENSIONS__ 1
#define _SVR3 1
#define mips 1
#define unix 1

HPUX

#define hp9k8 1
#define __hppa 1
#define __hpux 1
#define __hpux__ 1
#define hp9000s800 1
#define PWB 1
#define _PA_RISC1_1 1
#define __hp9000s700 1
#define __hp9000s800 1
#define __PWB__ 1
#define __GNUC_MINOR__ 7
#define hppa 1
#define hpux 1
#define _HPUX_SOURCE 1
#define __hp9k8__ 1
#define __hppa__ 1
#define __unix 1
#define __unix__ 1
#define __hp9k8 1
#define __GNUC__ 2
#define __hp9000s800__ 1
#define __PWB 1
#define unix 1

Minimum and Maximum Operators in C++

It is very convenient to have operators which return the "minimum" or the "maximum" of two arguments. In GNU C++ (but not in GNU C),

a < b

is the minimum, returning the smaller of the numeric values a and b;

a > b

is the maximum, returning the larger of the numeric values a and b. These operations are not primitive in ordinary C++, since you can use a macro to return the minimum of two things in C++, as in the following example.

#define MIN(X,Y) ((X) < (Y) ? : (X) : (Y))

You might then use int min = MIN (i, j); to set min to the minimum value of variables i and j.

However, side effects in X or Y may cause unintended behavior. For example, MIN (i++, j++) will fail, incrementing the smaller counter twice. A GNU C extension allows you to write safe macros that avoid this kind of problem (see Naming an Expression's Type). However, writing MIN and MAX as macros also forces you to use function-call notation for a fundamental arithmetic operation. Using GNU C++ extensions, you can write int min = i < j; instead.

Since < and > are built into the compiler, they properly handle expressions with side-effects; int min = i++ < j++; works correctly.

GnuPG

자세한 것은 GnuPG를 참고.

키 만들기

다음과 같이 한쌍(DSA 마스터 서명 키와 ?EIGamal 암호화 서브키)를 만듭니다. 생성할 키의 종류를 묻는데 기본값인 1 을 입력하거나 그냥 엔터를 치면 됩니다.

$ gpg --gen-key
gpg (GnuPG) 1.2.4; Copyright (C) 2003 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.

Please select what kind of key you want:
   (1) DSA and ElGamal (default)
   (2) DSA (sign only)
   (4) RSA (sign only)
Your selection?

다음 키 크기도 일반적인 1024를 선택합니다.

DSA keypair will have 1024 bits.
About to generate a new ELG-E keypair.
              minimum keysize is  768 bits
              default keysize is 1024 bits
    highest suggested keysize is 2048 bits
What keysize do you want? (1024)

다음은 키의 유효 기간을 정해 줄 수 있는데 기본값인 0은 만기일 없이 계속 사용한다는 뜻입니다.

Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Is this correct (y/n)? y

사용자 ID를 결정하는데 영문 이름과 이메일 주소, 간단한 주석을 차례로 적어 줍니다.

You need a User-ID to identify your key; the software constructs the user id
from Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: 여기에 이름
Email address: 여기에 이메일주소
Comment:
You selected this USER-ID:
    "이름 <이메일주소>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

입력한 정보가 모두 맞다면 o를 누르고 계속합니다. 이제 인증키 암호(passphrase)를 입력할 차례입니다. 암호를 두번 정확히 입력하면 키를 생성하기 시작하는데 "Not enough random bytes available. Please do some other work.... blah... blah"와 같은 메세지가 나오면서 키 생성이 멈추는 경우 os 엔트로피(entropy)를 증가 시키도록 딴짓(마우스를 흔들거나...)을 좀 해주면 됩니다.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
+++++.+++++.+++++.+++++.++++++++++..+++++++++++++++.+++++++++++++++++++++++++.++
+++++++++++++++++++++++++++++++++.++++++++++++++++++++++++++++++>+++++..........
......+++++

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 215 more bytes)
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
+++++.+++++++++++++++..+++++.+++++++++++++++.+++++...+++++++++++++++++++++++++++
++++++++.+++++++++++++++++++++++++++++++++++.+++++++++++++++>.+++++.....<...++++
+...........>+++++..<+++++......................................................
.....>+++++...........................................+++++^^^
public and secret key created and signed.
key marked as ultimately trusted.

이제 키가 다 만들어 졌으면 철회 인증서 (revoke key)도 만들어 두어야 합니다.

$ gpg --out revoke.asc --gen-revoke 이름

sec  1024D/8745B520 2004-07-05   이름 <이메일주소>

Create a revocation certificate for this key? y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 1
Enter an optional description; end it with an empty line:
>
Reason for revocation: Key has been compromised
(No description given)
Is this okay? y

만들어진 철회 인증서 (revoke.asc) 따로 잘 보관합니다.

공개키 만들기

외부에 공개하는 자신의 공개키는 --export 옵션을 사용하여 다음과 같이 만들면 됩니다.

$ gpg --out 저장할파일명 --armor --export 메일주소

참고로 내 공개키는 아래와 같습니다.


-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.9 (GNU/Linux)

mQGiBEoYEJ0RBACzpusLnvn0d8uX6fRWZKHPczGqEpj6+5+zEF12tM7yUP7MpNbX
cKWFe6E5rOszylHhHH7pIzUYqRefrdJ/dBo/CwL9aF9dwaVPa7UOTtk1eAH0O6hX
jnjO3gFCkZv49gxYElPtI8tlgbzi+uZKXl/e81c1/IifRGs//MEFiAr3qwCg0kEb
OMk6XNRFol6by7m67qH+vj8EAJ7yE5cGHV5qhu9JoSeK13U443iEalU8dmtScbV2
pND3G8VfYjkwnbF1c5ChmghwMpcbIPO83Ar8mhHm3WDuJVzqAfLWFPeg8ww/nuyK
8G05ivngF8CbYKO0J0Q5UAszWvxhEEmS3+/pV8mhv30M0XuqhPH4A+rhHZBxDQGV
VwXxA/4zKdMYh1SH2W36Af7z2P0bG724p5NCAx4L/rlKI8BbHyQ7HiH1fotf+3Gx
qbElAHoHQJy5pDCOsYuNFCmaUQi/BKv2NJb9XFHuFyY3L05yUMPWr3wTTQc9TZSu
MP4RK2+flFbTVE2d802dNxoxIQZkRRWpSQc0T0iL97H4VHXPLLQmWXVuLXlvbmcg
Q2hvaSA8eXVueW9uZy5jaG9pQGdtYWlsLmNvbT6IYAQTEQIAIAUCShgQnQIbIwYL
CQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJECLjV6Aiglz4OmoAn1b77PyPJff7PyAo
uTRZylZ3vknKAKC4CilkIzF1MG7+6LFkfjo4xrRv9rkCDQRKGBCdEAgA7KdS2sz+
j/Ii3GRSXL7R4+f6fGMvzJwg1nJWeCvyrDL9U9J5glp0aHhxHLUZPKYa7Lk3SAEH
ooUg2Tzm/nN8ciCmjTlp6nGR1r3SzrHQC8v5DRoF4IBKPPFBBS2rU94fMUbMSCU8
Sm9qtogxAGlJ3YSL+L3LAX9LbuK0Bcs88mbbPK51qVA+7b0x5fq1hELs53k7VpfE
yrc8z8xAORv5N2uLNugboaSH2jv3xZ5yw5ugfbA171pX9/gqqEBQANPLqiOvidTs
gsuCyiVoxq/Av2Rwk5W5ZYTkjV0nTysWa1VnSKMNp896EGksWH5VYnRC6cMyARbP
cn3Ndb0cC/rA7wADBQgApPyGMYTqWE7+eW/OVcQ29NUKkvHHosqNT7Gts9cCEnga
V/ldr8ZUJLGrmFNtdmubMvo5rQdFp3Kl+vnnoyfDHWmZPSpo9vtN9G/09tWa41Oy
tLyAE8HABWhtl7Mk9M3MMnNQu7tzOWqEPUAkrljaGfwEBFK33Df69Rzk+wAxlucy
jZrxPfF9e05/43th+rYY3hUPqWCuCEMY8rTTFG9RDCrqQOwzSrUEJU3nzG5zU5qa
Df5amLduUvqfv/60VE/xCM6l5DGqr2djh8j6IG6ma21nicfB6k/k86xaEL+ssaHz
RbLBh9RSZj6ZKGiAKhFe14etB/rEEKjha/UX0oIOTohJBBgRAgAJBQJKGBCdAhsM
AAoJECLjV6Aiglz4KuoAn253QLX5+cV2B75BlIGGMaYS+A24AJ9B8y0UjXMICH5B
lE6cRED5ZZaTNw==
=XmLu
-----END PGP PUBLIC KEY BLOCK-----

공개키 포함시키기

기본적으로는 아래 명령을 수행하면 됩니다.

$ gpg --import 공개키파일명

이 상태만으로는 사용할 수 없고 몇가지 절차를 거쳐야 합니다.

우선 키 편집으로 들어갑니다.

$ gpg --edit-key 사용자ID

여기서 사용자ID는 키를 식별할 수 있는 내용(이름이나 이메일 주소. 보통은 이메일 주소가 중복되지 않기 때문에 이메일 주소를 씁니다)을 적습니다.

편집 상태로 들어가면 몇 가지 명령을 받아들이는 Command> 프롬프트 상태가 됩니다. 여기서 지문을 확인하려면 fpr, 점검하려면 check를 입력합니다. 아래는 수행 예입니다.

$ gpg --edit-key gildong@alzzalinux.com
gpg (GnuPG) 1.0.0; Copyright (C) 1999 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.

pub  1024D/9F1AE76D  created: 2000-01-15 expires: never      trust: -/q
sub  1024g/EB42A0A8  created: 2000-01-15 expires: never
(1)  Gil-Dong Hong (Legendary Hero) <gildong@alzzalinux.com>

Command> fpr
pub  1024D/9F1AE76D 2000-01-15 Gil-Dong Hong (Legendary Hero) ......
        Fingerprint: ED8D 6EA3 062C E480 D619  CD4B 27A0 E471 9F1A E76D

Command> check
uid  Gil-Dong Hong (Legendary Hero) <gildong@alzzalinux.com>
sig!       9F1AE76D 2000-01-15   [self-signature]

보통은 fpr에서 얻은 Fingerprint 값이 진짜인지 확인하고(공개키 주인에게 물어보면 되겠지요 ) Command> 프롬프트에서 sing 해줍니다.

Command> sign

GnuPG를 이용한 파일 암호화

받을 사람만 풀 수 있도록 암호화 합니다. 이때 받을 사람의 공개키를 가지고 있어야 합니다.

암호화

$ gpg --output 출력파일명 --encrypt --recipient 받을사람ID 암호화할파일명

복호화

파일을 풀기 위해서는 간단합니다.

$ gpg --output 출력파일명 --decrypt 암호화된파일명

Enter passphrase:\

자신의 비밀키의 passphrase를 넣으면 복호화됩니다.

GnuPG를 이용한 서명

서명은 암호화와 다르게 자신의 비밀키를 사용합니다.

$ gpg --sign 뒤에서명을붙일파일명

서명 확인을 위해서는 자신의 공개키가 필요하며 아래와 같이 확인할 수 있습니다.

$ gpg --verify signed.txt
gpg: Signature made Sun 16 Jan 2000 05:04:51 AM KST using DSA key ID ...
gpg: Good signature from "Man-Yong Lee (Alzza Man, Bryan) ......
$ gpg --output plain.txt --decrypt singed.txt\

--sign 명령으로 서명을 붙인 파일은 바이너리 파일입니다. 따로 ASCII 파일로 서명을 붙이고 싶다면

$ gpg --clearsign 뒤에서명을붙일파일명

하면 파일명.asc 파일이 생성됩니다.

별도 서명

--detach-sig 명령 옵션을 사용하면 서명만 따로 만들어 줍니다.

$ gpg --detach-sig plain.txt
$ gpg --verify plain.txt.sig plain.txt

파일명에 .sig가 붙은 별도 서명 파일이 만들어집니다. 이 두 개를 모두 전송하면, 받은 쪽에서는 --verify 명령 옵션으로 별도 서명과 원본 파일(서명이 들러붙거나 하지 않은)을 가지고 확인할 수 있습니다. 확인한 후에는 별도 서명 파일만 지우고 원본을 읽으면 됩니다.