DNA 포럼 API 서비스 모음 DNA Lens

Daum 오픈 API 서명 방법

서명 값 만들기 #

1. 오픈 API 호출 url 구성 #

  • apikey는 반드시 포함되어 있어야 합니다.
http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b
&q=worldcup&results=10&start=1&output=rss
  • apid가 추가된 경우
http://apis.daum.net/search/dsa?apid=ba8c53ab7970189d93a7
&apikey=4125603e35da5d8820b07dc7b19050dbc838336b
&q=worldcup&results=10&start=1&output=rss

2. ts, nonce 생성 및 오픈 API 호출 url 에 포함 #

http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b
&q=worldcup&results=10&start=1&output=rss
&ts=20060911061201
&nonce=f91cbfbaa8477afd

3. 서명 #

  • 2번의 결과 url 에 HMACSHA1 서명 알고리즘을 수행합니다. ts 와 nonce 값이 항상 변하기 때문에 실제 아래 서명값은 항상 다른 값이 나오게 됩니다.

  • HMACSHA1 서명 알고리즘은 RFC 2014 에 정의되어 있습니다.
서명 대상 데이터 := "http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b
&q=worldcup&results=10&start=1&output=rss&ts=20060911061201&nonce=f91cbfbaa8477afd"

sig := hmacsha1( 서명 대상 데이터 ) with signature key

서명값 예 : b45de8a31aed6e58b831dd72087bb4ed71fcaf98

4. 서명 url 생성 #

  • 2번 결과 url에 "sigalg=hmacsha1&sig=서명값" 을 추가합니다.
http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b
&q=worldcup&results=10&start=1&output=rss
&ts=20060911061201
&nonce=f91cbfbaa8477afd
&sigalg=hmacsha1
&sig=b45de8a31aed6e58b831dd72087bb4ed71fcaf98

http://apis.daum.net/search/dsa?apid=ba8c53ab7970189d93a7
&apikey=4125603e35da5d8820b07dc7b19050dbc838336b
&q=worldcup&results=10&start=1&output=rss
&ts=20060911061020
&nonce=068e146a0e591cf3
&sigalg=hmacsha1
&sig=3bc3cfffdc67c3e080646ca53ac4d5ccb3b6bca3

5. 서명 API 호출 #

  • 이 url 로 api를 호출합니다.

서명 생성 샘플 코드 #

Java #

import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Calendar;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

public class DaumOpenApiSign {
	
	private static final Log log = LogFactory.getLog(DaumOpenApiSign.class);
	
	static {
		Security.addProvider(new BouncyCastleProvider());
	}
	public static final int NONCE_BYTE_LENGTH = 8;
	static SecureRandom random = null;
	static {
		try{
			random = SecureRandom.getInstance("SHA1PRNG");
			byte[] seed = random.generateSeed( 20);
			random.setSeed( seed );
			log.info( "SecureRandom Generator for OpenAPI Signature is created.");
		} catch ( NoSuchAlgorithmException e) {
			log.fatal( "Fail to create SecureRandom Generator for OpenAPI Signature.");
		}
	}
	
	static final String HMAC_SHA1_ALGORITHM_NAME = "hmacsha1";
	
	private static void appendZeroString( StringBuffer buffer, int value) {
		if ( value < 10 ) {
			buffer.append( '0');
		}
		buffer.append( value );
	}
	
	public static String generateTimeStamp() {
		Calendar rightNow = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00"));
		StringBuffer timeStamp = new StringBuffer( 14 );
		timeStamp.append( rightNow.get(Calendar.YEAR));

		appendZeroString( timeStamp, rightNow.get(Calendar.MONTH) + 1);
		appendZeroString( timeStamp, rightNow.get(Calendar.DATE));
		appendZeroString( timeStamp, rightNow.get(Calendar.HOUR_OF_DAY));
		appendZeroString( timeStamp, rightNow.get(Calendar.MINUTE));
		appendZeroString( timeStamp, rightNow.get(Calendar.SECOND));
		return timeStamp.toString();
	}

	public static String generateNonce() {
		byte[] nonce = new byte[NONCE_BYTE_LENGTH];
		random.nextBytes( nonce );
		return new String( Hex.encode(nonce));
	}

	private static String __sign ( String alg, String key, String toBeSigned ) {
		String signature = null;
		
		if ( alg.equals(HMAC_SHA1_ALGORITHM_NAME)) {
			try {
				Mac mac = Mac.getInstance("HMACSHA1","BC");
				byte[] mac_result;
				Key mac_key = new SecretKeySpec(Hex.decode(key), "HMACSHA1"); // Convert to key object.
				mac.init(mac_key); // Initialize.
				mac_result = mac.doFinal( toBeSigned.getBytes("UTF-8"));
				signature = new String( Hex.encode( mac_result ) );
			} catch ( Exception e) {
				e.printStackTrace();
			}
		}
		return signature;
	}
	
	public static String sign ( String api_call_url, String alg, String key ) throws SignErrorException {

		String auth_param_ts = generateTimeStamp();
		String auth_param_nonce = generateNonce();
		String auth_param_sig_alg = alg;
		
		StringBuffer toBeSignedBuffer = new StringBuffer(512);

		toBeSignedBuffer.append( api_call_url );
		toBeSignedBuffer.append( "&ts=" );
		toBeSignedBuffer.append( auth_param_ts );
		toBeSignedBuffer.append( "&nonce=" );
		toBeSignedBuffer.append( auth_param_nonce );
		
		String signature = __sign ( auth_param_sig_alg, key, toBeSignedBuffer.toString() );

		toBeSignedBuffer.append( "&sigalg=" );
		toBeSignedBuffer.append( auth_param_sig_alg );
		toBeSignedBuffer.append( "&sig=" );
		toBeSignedBuffer.append( signature );
		
		return toBeSignedBuffer.toString();
	}
	
	public static void main(String[] args) {
		
		String api_url = "http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b&q=worldcup&results=10&start=1&output=rss";
		String signature_key = "8e4d0a924c60e65ccc38b7f9958f37ff5105f8e1";
		try {
			String signed_api_url = DaumOpenApiSign.sign( api_url, "hmacsha1", signature_key);
			
			System.out.println( "api url   : [" + api_url + "]" );
			System.out.println( "signed api url : [" + signed_api_url + "]" );
		} catch ( Exception e) {
			e.printStackTrace();
		}
	}
}


  • 실행 결과
api url   : [http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b&q=worldcup&results=10&start=1&output=rss]
signed api url : [http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b&q=worldcup&results=10&start=1&output=rss&ts=20060911095728&nonce=af414a6a14b32837&sigalg=hmacsha1&sig=2484ed77cc3bafb93b74c77697c53d1f6cff1424]

자바스크립트(Javascript) #

<script type="text/javascript" src="sha1.js"></script>
<script type="text/javascript" src="daumopenapi.js"></script>

<script type="text/javascript" >
var api_call_url="http://apis.daum.net/search/dsa?apikey=4125603e35da5d8820b07dc7b19050dbc838336b&q=worldcup&results=10&start=1&output=rss";
var sigalg="hmacsha1";
var sigkey="8e4d0a924c60e65ccc38b7f9958f37ff5105f8e1";

signed_api_url = daumOpenAPI_Sign_URL ( api_call_url, sigalg, sigkey );
alert(signed_api_url);
</script>

PHP #

<?php

function Daum_OpenAPI_Sign( $api_call_url, $sig_key ) {
	$bin_sig_key = pack ( "H*" , $sig_key );
	
	$timestamp = gmdate( 'YmdHis' );
	$nonce = "";
	for ( $i=0; $i< 8 ; $i++) {
	   $hex_byte = sprintf("%02s", dechex( mt_rand(0,255))); 
	   $nonce = $nonce . $hex_byte;
	}

// echo "timestamp : " . $timestamp . "\n";
// echo "nonce : " . $nonce . "\n";
// echo "Signature Key : " . $sig_key . "\n";

	$to_be_signed_str = $api_call_url . '&ts=' . $timestamp . '&nonce=' . $nonce ;
	$signature = hash_hmac ( 'sha1', $to_be_signed_str , $bin_sig_key );
	$signed_api_call_url = $to_be_signed_str . '&sigalg=hmacsha1&sig=' . $signature;
	return $signed_api_call_url;
}

$apiurl = 'http://apis.daum.net/search/dsa';
$apid = 'f9e17aa76bd1c346d8b4';
$apikey = '55312a081c1f57a77f5f0d755e51bbd795ab6b37';
$api_param = 'q=worldcup&results=10&start=1&output=rss';

$sig_key = '4360b51cf4931ffe6985ddcb474a8337453534e3'; 

echo "apiurl : " . $apiurl . "\n";
echo "apid : " . $apid . "\n";
echo "apikey : " . $apikey . "\n";
echo "api_param : " . $api_param . "\n";

$api_call_url = $apiurl . '?apid=' . $apid . '&apikey=' . $apikey . '&' . $api_param ;
echo "API Call URL : " . $api_call_url . "\n";

$signed_api_call_url = Daum_OpenAPI_Sign ( $api_call_url, $sig_key );
echo "Signed API Call URL : " . $signed_api_call_url . "\n";
?>