본문으로 건너뛰기

Full Stack JavaScript Developer | Half-time Open Sourcerer.

모든 저자 보기

Docker와 Docker-compose 제대로 설치하기

· 약 2분

구글링하면 너무 예전 버전 (1버전 대)의 설치방법만 나와있다.

영문을 따라할 수 있으면 공홈을 보고하면 된다.

Docker 설치

옛 버전 삭제

$ sudo yum remove docker \
docker-common \
docker-selinux \
docker-engine

서비스를 내리고 docker를 삭제해도 /var/lib/docker/ 폴더는 지워지지 않고 여기에 기존 데이터가 모두 남아있다.

필수 패키지 설치

$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
## docker repo를 등록한다.
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
## yum package를 업데이트
$ sudo yum makecache fast

다운로드

sudo yum install docker-ce

실행

$ sudo systemctl start docker
$ sudo systemctl enable docker

$ sudo docker --version
Docker version 17.06.0-ce, build 02c1d87

Docker-compose 설치

다운로드

## root로 로그인해야한다.
$ curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

실행 권한 부여

$ chmod +x /usr/local/bin/docker-compose

## 설치 확인
$ docker-compose --version
docker-compose version 1.14.0, build 1719ceb

설치가 완료되었다.

Centos6에서 설치하기

centos6 버전에서는 위의 설치방법으로 Docker를 설치할 수 없다. (RHEL7 버전 전용이기에) 다음과 같이 설치하자.

yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm

yum install -y docker-io

service docker start

chkconfig docker on

Docker Error response from daemon: reference does not exist

· 약 1분

Docker rmi명령어로 이미지를 삭제하는데 Error response from daemon: reference does not exist 오류가 나면서 이미지 삭제가 안 되는 경우 다음과 같이 하면된다.

해결

구글링하면 다시 설치하거나 cache를 비우거나 하라는데 해결되진 않았고 쉽게 접근하면 된다. 그냥 이미지 폴더를 날리자

sudo systemctl stop docker
sudo rm -rf /var/lib/docker
sudo systemctl start docker

Linux 폴더 구조

· 약 2분

윈도우도 Program Files 가 무슨 폴더인지 보자마자 알듯 리눅스도 폴더명이 친숙해지면 더 쉬워지지 않을까 했다. (보통 /home, /etc, /var, /tmp 정도만 왔다 갔다 하니까) 이 정도만 정리해 놓으면 CPU 정보를 볼때 왜 /proc/cpuinfo를 까야되는지 한 번에 감이 올 것 같다.

Directory Structure

경로설명
/Root
/bin기본 명령어 프로그램 (ex. ls, cp)
/dev장치 파일
/etc시스템 설정 및 사용자 정보, 네트워킹 설정 파일
/home유저 폴더
/lib실행파일이 사용할 수 있는 공유 라이브러리 코드 파일
/proc시스템 통계
/sys장치와 시스템 인터페이스 제공
/sbin시스템 실행 파일
/tmp임시 파일
/usr리눅스 시스템 파일 (사용자 파일이 아님)
/var변수 서브디렉토리로 프로그램 런타임 정보 기록
/boot커널 부트 로더 파일
/media제거 가능한 미디어를 위한 마운트 포인트
/opt제3자 소프트웨어 파일
/usr/includeC컴파일러 헤더파일
/usr/infoGNU 정보 매뉴얼
/usr/local관리자 소프트웨어 설치 파일
/usr/man매뉴얼 페이지
/usr/share다른 유닉스 머신과 작업해야 할 파일
/vmlinuz 또는 /boot/vmlinuz리눅스 커널

여담

Linux Kernel을 이해하는 그 날까지

Laravel - Log::debug vs logger

· 약 1분

로그를 찍기 위해서 Log 파사드 또는 logger 헬퍼 함수를 사용할 수 있다.

두 함수의 차이점은 무엇일까?

Log::debug

  • Log 파사드가 정의되어있어야 한다. use Log;
  • NULL 값이 들어올시 NULL이 로그에 출력된다.

logger

  • 헬퍼함수라 Log 파사드 없이 사용 가능하다.
  • NULL 값이 들어올시 아무 내용도 찍히지 않는다.
  • debug 레벨이 기본이라, 다른 레벨의 로그를 찍으려면 logger()->error('에러 로그'); 처럼 함수를 하나 더 호출해야한다.
  • 단, info 레벨 로그는 info(); 헬퍼 함수를 사용할 수 있다.

Laravel 5.5 - 일본으로 메일 보내기

· 약 3분

일본 통신사 중 소프트뱅크와 AU는 UTF8 메일이 깨져서 들어간다. (도코모는 정상적) Laravel 뿐아니라 일본으로 메일을 보내고 싶다면, 이 포스팅의 방식대로 접근하면 된다.

iso-2022-jp

먼저 인코딩을 iso-2022-jp로 바꿔줘야한다.

테스트 결과 JIS 인코딩과 같다. SJIS 인코딩도 있는데 위 인코딩에 몇가지 특수문자가 추가된 형태이다.

AppServiceProvider에 메일 인코딩을 전역으로 설정하자.

app/Providers/AppServiceProvider.php
<?php
...
use Swift;
use Swift_DependencyContainer;
use Swift_Preferences;

class AppServiceProvider extends ServiceProvider
{
...
public function register() {
// laravel의 메일 패키지는 Swift이므로 당황하지말자
Swift::init(function() {
// 헤더를 추가하고
Swift_DependencyContainer::getInstance()
->register('mime.qpheaderencoder')
->asAliasOf('mime.base64headerencoder');
// 인코딩을 변경한다.
Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
});
}
}

7bit

위키를 참조해보면 iso-2022는 문자열을 7bit 또는 8bit로 표현하는 기술이다. 근데, 소프트뱅크 문서에 7bit로 달란다. 메일 폼을 열어서 build시에 인코딩 바이트를 변경하자.

app/Mail/YourMailForm.php
<?php
...
use Swift_Mime_ContentEncoder_PlainContentEncoder;

class YourMailForm extends Mailable
{
...
public function build() {
return $this->subject('ご注文を承りました。')
->view('mail.your_mail_view')
->withSwiftMessage(function($message) {
// 전역으로 설정한 뒤에 이 메소드를 빼보고 테스트를 못 해봤다.
// 다음 분이 빼고 테스트 부탁드려요 : )
$message->setCharset('iso-2022-jp')
// 인코딩 바이트를 바꿔준다.
->setEncoder(new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit'));
});
}
}

mail.view

가장 중요한 것은 Mail View에서도 charset meta tag를 등록해줘야 한다는 것이다. 이 걸 세팅안하고 얼마나 삽질을 해댔는지, 없던 이두근이 생길지경.

resources/view/mail/your_mail_view.blade.php
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-2022-jp">
</head>
<body>
...
</body>
</html>

이렇게 세팅을 하고 메일을 보내면 정상적으로 보내지는 걸 확인할 수 있다.

여담

세 가지만 기억하자.

  • iso-2022-jp
  • 7bit
  • meta[charset="iso-2022-jp"]

AWS 용어 정리

· 약 2분

AWS의 생태계에 들어가기 위해선 먼저 용어에 익숙해져야 될 것 같았다. 사용법은 쉬운데.. 약어가 처음 접하는 사람에게 조금 부담스러웠다.

용어

서비스명약어설명
Elastic Compute CloudEC2클라우드 서버
EC2 Container ServiceECSDocker 컨테이너 서버
Elastic Load BalancingELB트래픽, 부하 분산 서비스
Lambda-클라우드 Function
Scale Up-인스턴스 물리용량 증가
Scale Out-인스턴스 복제
Auto Scaling-인스턴스 Scale 자동화
Route 53-DNS 서비스
Virtual Private CloudVPC내부망 구축 서비스
Relational Database ServiceRDSRDBMS 구축 서비스
DynamoDB-NoSQL 구축 서비스
Simple Storage ServiceS3데이터 스토리지 서비스 (파일서버)
CloudFront-CDN 서비스
Glacier-저렴한 스토리지 서비스 (주로 백업용)
Elastic Block StoreEBSEC2의 가상 하드디스크
Identity and Access ManagementIAM인증, 권한 부여
CloudWatch-AWS 리소스 모니터링
Elastic BeanstalkEBPaaS
LightSail-저렴한 EC2 (VPS)

여담

전체적으로 GCP보다 용어가 직관적이지 않은 느낌 (App Engine, Compute Engine을 보면 얼마나 멋진가)이였는데, 풀어 놓고 적어보니 GCP도 AE, CE 이렇게 적으면 못 알아 먹었겠구나.

unpkg cdn 사용하기 (jsdelivr)

· 약 2분

최근 소스들을 까보다가 발견했는데, npm에 등록된 패키지를 CDN으로 바로 활용 가능한 서비스가 있다. 바로 unpkg이다. 리젼은 여기서 확인 가능하다.

사용

  • 사용법은 엄청나게 간단하다.
  • node_modules 폴더 안에 있는 구조를 URL에 그대로 입력만 해주면 된다. 몇 가지 예로 확인해보자.
<!-- React -->
<script src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
<!-- Lodash -->
<script src="https://unpkg.com/[email protected]/lodash.min.js"></script>
<!-- Bootstrap css -->
<script src="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css"></script>
  • node_modules 안의 경로가 생각나지 않는다 라면 폴더 경로까지만으로 웹에서 접근해보자.
  • 예를 들어 Bootstrap4라면 https://unpkg.com/[email protected] 까지만 들어가면 폴더 구조가 보인다.

여담

  • 블로그의 스크립트도 unpkg로 바꿨는데, 로딩속도가 1초 가까이 줄어든 느낌이다.

이슈

  • unpkg로 스크립트를 가져오는 도중에 503 timeout 에러가 발생해서 블로그가 동작하지 않았었다.
  • 같은 방법으로 동작하지만 좀 더 reliable한 서비스인 jsdelivr를 사용하자.

Laravel 5.5 - 로그인(Auth) 붙히기

· 약 11분

이전 포스팅에서 데이터를 가져왔으니, 로그인을 구현해보자.

Basic Auth

라라벨에서 제공하는 회원가입, 로그인, 비밀번호 찾기 기능을 사용하고 싶다면 artisan 명령어로 간단하게 시작할 수 있다.

php artisan make:auth

명령어를 실행하면 resources/views/auth 폴더에 뷰가 app/Http/Controllers/Auth에 로직이 생성되고 routes/web.php에 라우팅이 등록된다. DB도 같이 만들고 싶다면 Docs를 따라하자.

다른 테이블 사용

제공된 user 테이블을 안 쓰려면 커스터마이징이 필요하다.

설정 변경

config/auth.php 파일로 이동해 다른 모델을 등록하자.

config/auth.php
<?php
'providers' => [
'users' => [
'driver' => 'eloquent',
// 여기에 사용할 모델을 등록한다.
'model' => App\Models\Member::class,
]
]

config 안의 파일을 변경하면 config:clear를 실행해 혹시 모를 캐시를 날려주자

그리고 app/Models/Member.php로 이동해 내 모델을 라라벨 기본 인증 모듈을 사용할 수 있게 추가해야한다.

app/Models/Member.php
<?
// 라라벨 인증 사용
use Illuminate\Foundation\Auth\User as Authenticatable;
// 비밀번호 변경 메일을 위해 필요한 trait
use Illuminate\Notifications\Notifiable;

// Authenticatable 를 상속받는다.
class Member extends Authenticatable {
// Notifiable trait를 추가한다.
use Notifiable;

protected $guarded = [
'member_id', 'remember_token'
];

protected $hidden = [
'password', 'remember_token',
];
}

인증 필드 변경

Basic Auth는 기본 필드를 email로 잡고 있기 때문에 id 필드를 사용하게 변경해야한다.

app/Http/Controllers/Auth/LoginController.php
<?php
// username 메소드를 추가
public function username() {
// 반환할 필드를 선언한다.
return 'id';
}

회원가입 후 자동로그인

회원가입이 성공하면 세션을 생성해줘야한다.

app/Http/Controllers/Auth/RegisterController.php
<?php
// registered 메소드를 Override
protected function registered(Request $request, $user) {
// 세션 생성
Auth::attempt([
'id' => $request->input('id'),
'password' => $request->input('password')
]);

return response(null, 204);
}

ajax 처리

로그인

로그인을 ajax로 처리해야될 경우 커스터마이징이 필요하다.

app/Http/Controllers/Auth/LoginController.php
<?php
// authenticated 메소드를 Override
protected function authenticated(Request $request, $user) {
// 인증이 된 경우 페이지 전환이 아닌 전환될 페이지를 json으로 반환한다.
if ($request->ajax()) {
return response()->json([
'href' => url()->previous()
]);

} else {
return abort(405);
}
}

비밀번호 찾기

비밀번호 찾기를 ajax로 처리해야될 경우 커스터마이징이 필요하다.

app/Http/Controllers/Auth/ForgotPasswordController.php
<?php
public function sendResetLinkEmail(Request $request) {
$this->validateId($request);
// email이 아닌 아이디로 검색을 해 메일을 찾고 싶다면
$data = Member::where('id', $request->only('id'))
->first(['email']);

$email = isset($data->email) ? $data->email : null;

// 여기서 email이 User Model(Member Model)에 바인딩된다.
// 아래의 sendPasswordResetNotification 메소드에서 $this->email 값이다.
$response = $this->broker()->sendResetLink([
'email' => $email
]);

// 리턴 값을 변경해주자.
return response()->json([
'email' => $email
], $response == Password::RESET_LINK_SENT ? 200 : 500 );
}

routing 예외

ajax 요청으로 바꿨다면 굳이 필요없는 기본 route는 등록할 필요가 없다. (예를 들면 로그인 페이지) 먼저 routes/web.php에서 Auth::routes(); 를 지워주고 라라벨 route 파일을 열어보자.

vendor/laravel/Illuminate/Routing/Router.php
// 994 라인
public function auth()
{
// Authentication Routes...
$this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController@login');
$this->post('logout', 'Auth\LoginController@logout')->name('logout');

// Registration Routes...
$this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
$this->post('register', 'Auth\RegisterController@register');

// Password Reset Routes...
$this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
$this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
$this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
$this->post('password/reset', 'Auth\ResetPasswordController@reset');
}

입맛에 맞게 web.php로 가져와 사용하자.

notification 예외

Noticifation은 사용자에게 빠르게 알림을 보낼 수 있는 기능이지만, 정해져 있는 템플릿을 사용하므로 커스터마이징이 되게 힘들다. 비밀번호 찾기시에 보낼 메일을 정해진 템플릿을 사용할 수 없다면 메소드를 수정하자.

app/Models/Member.php
<?php
// 이 메소드를 override해야한다.
// 첫 파라미터는 비밀번호 인증용 token이 들어온다.
public function sendPasswordResetNotification($token) {
Mail::to($this->email)->send(new PasswordReset($token));
}

Auth

Basic Auth를 사용하는데 건드려야 되는 곳이 많으므로 Auth 모듈만 사용하는게 정신건강에 좋다고 본다. (Bootstrap 기반의 Laravel에 딱 맞는 모양을 입은 프로젝트라면 기본 인증이 좋겠지만)

로그인

먼저 사용할 모델에 Authenticatable 클래스를 상속 받자 그리고 LoginController에서 Auth::attempt() 메소드를 실행하면 끝이다.

app/Http/Controllers/LoginController.php
public function login(Request $request) {
$password = $request->password;

if(Auth::attempt([ 'id' => $request->id, 'password' => $password ])){
return response(null, 200);

}else{
return abort(401);
}
}

not bcrypt

Auth 모듈은 기본으로 bcrypt를 사용해 비밀번호를 암호화하고 비교하는데 다른 암호화 방식을 사용해야하는 경우가 있다. bcrypt를 사용하지 않게 처리해보자.

app/Models/Member.php
// 이 메소드를 override 해야한다.
public function getAuthPassword() {
// bcrypt 비교를 하지 않기 위해 강제로 해시를 생성한다.
return Hash::make($this->password);
}

이제 Auth::attempt() 메소드에 패스워드를 넘길 때 암호화를 해주고 넘기면 된다.

N개의 세션

관리자와 회원은 같은 세션을 사용하면 안 된다. 세션을 분기해보자.

모델 생성

먼저 모델을 하나 만들고 Authenticatable 클래스를 상속받는다.

app/Models/Admin.php
<?php

use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable {
// 속성은 테이블에 맞게 알아서 정리하자
}

설정 추가

만든 모델을 Laravel Auth에서 사용한다고 등록을 해줘야한다.

config/auth.php
<?php
return [
'guards' => [
...
// 아래에 등록된 provider를 admin이란 이름의 guard로 사용
'admin' => [
'driver' => 'session',
'provider' => 'admin'
]
],
'providers' => [
...
// 방금 만든 모델을 Auth의 Provider로 등록
'admin' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class
]
],
];

passowrds 속성은 제공되는 password_resets 기능을 사용할 경우에만 추가해주면 된다.

미들웨어

관리자 세션이 인증된 사람만 관리자 페이지에 접근할 수 있어야한다. php artisan make:middleware Admin 명령어를 실행해 Admin Middleware를 만들자.

app/Http/Middleware/Admin.php
<?php
use Auth;
use Closure;

class Admin {

public function handle($request, Closure $next) {
// admin session이 있는 경우만 request를 진행한다.
if (Auth::guard('admin')->check()) {
return $next($request);
}

// 아닐경우 관리자 로그인 페이지로 넘긴다.
return redirect()->route('admin.login');
}
}

그리고 Http Kernel에 방금 만든 Admin Middleware를 라우팅에서 사용할 수 있게 등록해준다.

app/Http/Kernel.php
<?php
...
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
// admin 이름으로 Admin Middleware를 호출할 수 있게 등록
'admin' => \App\Http\Middleware\Admin::class,
];

새로운 라우팅 파일로 관리하기 위해 RouteServiceProvider에 설정을 추가한다.

app/Providers/RouteServiceProvider.php
<?php
...
public function map() {
...
$this->mapAdminRoutes();
}

protected function mapAdminRoutes() {
// /admin 으로 들어오는 요청에 대해 처리한다.
Route::prefix('admin')
// 이런식으로 한 번에 추가할 수도 있다. 하지만 except 함수를 쓸 수 없는 것 같고,
// 라우팅 페이지에서 미들웨어를 등록해주는 게 더 편했다.
// ->middleware(['web', 'admin'])
->middleware('web')
->namespace($this->namespace)
// routes/admin.php 파일을 관리자 라우팅 파일로 등록한다.
->group(base_path('routes/admin.php'));
}

마지막으로 라우팅 파일에 미들웨어를 넣어준다.

routes/admin.php
<?php
// admin middleware를 사용하고, namespace에 admin.을 추가한다.
Route::group(['middleware' => 'admin', 'as' => 'admin.'], function() {
// 이 라우팅은 route('admin.main') 으로 접근이 가능해진다.
Route::get('/', 'AdminController@index')->name('main');
});

활용

기존 Auth 메소드들에 guard만 추가해주면 쉽게 사용 가능하다.

<?php
Auth::guard('admin')->attepmt();
Auth::guard('admin')->check();
Auth::guard('admin')->user();
Auth::guard('admin')->logout();

로그아웃

Auth::logout() 메소드를 호출하면 된다.

이슈

세션 아이디

라라벨에선 로그인을 할 때 세션아이디를 새로운 값으로 엎어쳐버린다. 따라서 같은 환경에서 접근했는데, 로그인을 하면 다른 사용자가 되는 경우가 생긴다. (로그아웃시에는 그대로다.)

<?php
// 로그인 전에 세션아이디를 가져와
$old_session_id = Session::getId();
// 로그인이 성공하면 DB에서 등록된 세션값을 업데이트하자.

소셜 로그인

laravel/socialite 패키지를 설치하고 아주 쉽게 연동이 가능하다.

세팅

composer require laravel/socialite

기본 socialite 패키지는 facebook, twitter, linkedin, google, github or bitbucket 만 연동이 가능하므로 다른 소셜 로그인을 연동하고 싶을 경우 Socialite Providers 패키지를 사용하면 된다.

Socialite Providers 사이트에는 Naver, Kakao, BattleNet(?) 등의 소셜 연동이 가능한 패키지가 무수히 많다.

여담

JWT 인증과 같이본다면 Laravel을 사용한 실무에서 필요한 인증은 다 마무리한 셈일 듯

PHP 7.1에서 mcrypt 대체하기

· 약 3분

MCRYPT

  • 암호화 함수인 mcrypt 가 PHP 7.1 버전부터 Deprecated 되었다.
  • 왜 사라졌는지는 링크에 자세하게 나와있다.

기존 소스

  • PHP 구버전에서는 mcryptMCRYPT_RIJNDAEL_128 알고리즘을 통해 AES128 이 구현되어 있을 것이다.
  • MCRYPT_RIJNDAEL_128AES 128동일하다.
  • 타 언어와는 조금 다른데, 호환을 위해선 pkcs5 padding 으로 변경해주는 작업이 필요하다.
  • php mcrypt function 의 기본 패딩은 zeros padding
<?php
// 이런 식이거나
$cipherText = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, pkcs5_pad($plainText), MCRYPT_MODE_CBC, $iv);

// 이런 식일 것
$td = mcrypt_module_open("rijndael-128", "", "cbc", "");
@mcrypt_generic_init($td, $key, $iv);
$cipherText = @mcrypt_generic($td, pkcs5_pad($plainText));
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

function pkcs5_pad($text, $blockSize = 16) {
$pad = $blockSize - (strlen($text) % $blockSize);
return $text . str_repeat(chr($pad), $pad);
}

대안

  • PHP 5.3 부터 사용 가능한 openssl_encrypt 함수를 쓰면 된다.
  • openssl 확장 모듈이 설치되어야한다.

OPENSSL

Encrypt

<?php
$cipherText = openssl_encrypt($plainText, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
// decrypt에서 오류가 발생해 PKCS5로 패딩을 맞춰주고 보내야한다면.
$cipherText = openssl_encrypt(pkcs5_pad($plainText), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);

Decrypt

<?php
$plainText = openssl_decrypt($cipherText, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
// unpad가 필요하다면
$plainText = pkcs5_unpad(openssl_decrypt($cipherText, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv));

function pkcs5_unpad($text) {
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) {
return $text;
}
if (!strspn($text, chr($pad), strlen($text) - $pad)) {
return $text;
}
return substr($text, 0, -1 * $pad);
}

PKCS5 vs PKCS7

  • openssl_encrypt의 default padding 은 PKCS7 padding 인데, 어떻게 호환이 되는 것일까?
  • 여기서 해답을 찾았다.

The difference between the PKCS#5 and PKCS#7 padding mechanisms is the block size; PKCS#5 padding is defined for 8-byte block sizes, PKCS#7 padding would work for any block size from 1 to 255 bytes. So fundamentally PKCS#5 padding is a subset of PKCS#7 padding for 8 byte block sizes. so, data encrypted with PKCS#5 is able to decrypt with PKCS#7, but data encrypted with PKCS#7 may not be able to decrypt with PKCS#5.

triple des

  • des-ede3-cbc가 triple des 알고리즘이다.
<?php
// encrypt
openssl_encrypt($text, "des-ede3-cbc", $key, OPENSSL_RAW_DATA, $iv);

// decrypt
openssl_decrypt($cipherText, "des-ede3-cbc", $key, OPENSSL_RAW_DATA, $iv);

패키지

  • 이 모든 걸 커버하는 라이브러리를 사용하자. phpseclib/mcrypt_compat
  • phpseclib 는 laravel/passport 에서도 사용되었다.

여담

카카오페이가 PHP 5 버전만 지원해 문의해봤지만 계획이 없어 이번 기회에 모듈을 다 뜯어봤는데 MCRYPT 만 만져주면 정상적으로 결제가 되었다.

곧 이 짓을 안해도 될 듯하다. KakaoPay 종료

Paypal 기부 버튼 만들기

· 약 1분

기존에 Paypal 버튼을 만들기가 되게 복잡했는데, 최근 Paypal.Me 가 생기면서 아주 간단해졌다!

Paypal.Me에 들어가서 서비스 가입만 하면 된다. Paypal 계정이 없으면 가입 후에 계좌 인증이 필요하다

소스

아래 소스를 추가해주자. 기존 페이팔 버튼의 소스에서 action 부분만 변경해주었다.

<!-- https://www.paypal.me/GracefulLight/3 으로 금액을 붙혀 보내면 초기 금액을 설정할 수 있다. -->
<form action="https://www.paypal.me/GracefulLight" method="get" target="_blank">
<table border="0" cellpadding="10" cellspacing="0" align="center">
<tr>
<td align="center"></td>
</tr>
<tr>
<td align="center">
<input
type="image"
src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/PP_logo_h_100x26.png"
alt="Donate"
border="0"
name="submit"
/>
</td>
</tr>
</table>
</form>

결과

image from hexo

새삼 예쁜 것 같다.